From b47edc9670aa01cbe4c5458ecfa88fbd41bd30ad Mon Sep 17 00:00:00 2001 From: Spring Burst <16273755+Andor233@users.noreply.github.com> Date: Tue, 10 May 2022 20:05:08 +0800 Subject: [PATCH 01/31] =?UTF-8?q?Update=20=E6=A8=A1=E6=8B=9F=E5=99=A8?= =?UTF-8?q?=E6=94=AF=E6=8C=81.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/模拟器支持.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/模拟器支持.md b/docs/模拟器支持.md index 8c9efc2a16..405b5b63e5 100644 --- a/docs/模拟器支持.md +++ b/docs/模拟器支持.md @@ -53,6 +53,7 @@ ### Win11 WSA +下载 [adb](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) ,将 `platform-tools` 文件夹解压到 `MeoAsstGui.exe` 的同级目录 勉强支持。但 WSA 的截图经常莫名其妙截出来一个白屏,导致识别异常,不推荐使用 ### AVD From a71e7b894e9341486ed844e9c376dd134f4b0e21 Mon Sep 17 00:00:00 2001 From: Spring Burst <16273755+Andor233@users.noreply.github.com> Date: Tue, 10 May 2022 22:26:51 +0800 Subject: [PATCH 02/31] =?UTF-8?q?Update=20=E6=A8=A1=E6=8B=9F=E5=99=A8?= =?UTF-8?q?=E6=94=AF=E6=8C=81.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/模拟器支持.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/模拟器支持.md b/docs/模拟器支持.md index 405b5b63e5..6331e7898f 100644 --- a/docs/模拟器支持.md +++ b/docs/模拟器支持.md @@ -53,8 +53,9 @@ ### Win11 WSA -下载 [adb](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) ,将 `platform-tools` 文件夹解压到 `MeoAsstGui.exe` 的同级目录 -勉强支持。但 WSA 的截图经常莫名其妙截出来一个白屏,导致识别异常,不推荐使用 +勉强支持。 +- 需要下载 [adb](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) ,将 `platform-tools` 文件夹解压到 `MeoAsstGui.exe` 的同级目录 +- 但 WSA 的截图经常莫名其妙截出来一个白屏,导致识别异常,不推荐使用 ### AVD From 3a210bb0bdf073b54fcf4c957b38a92b30b957ba Mon Sep 17 00:00:00 2001 From: alexzhang Date: Wed, 11 May 2022 07:12:42 +0800 Subject: [PATCH 03/31] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86linux=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E6=97=B6logger.hpp=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit linux编译时会报错 ``` In file included from /home/alexzhang/code/maa-building/MaaAssistantArknights/src/MeoAssistant/AbstractConfiger.cpp:6: /home/alexzhang/code/maa-building/MaaAssistantArknights/src/MeoAssistant/Logger.hpp: In member function ‘void asst::Logger::log(std::string_view, Args&& ...)’: /home/alexzhang/code/maa-building/MaaAssistantArknights/src/MeoAssistant/Logger.hpp:136:52: error: ‘std::this_thread’ has not been declared 136 | level.data(), getpid(), std::this_thread::get_id() | ^~~~~~~~~~~ ``` 添加了 `#include `后问题解决 --- src/MeoAssistant/Logger.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/MeoAssistant/Logger.hpp b/src/MeoAssistant/Logger.hpp index 95697ac18a..9520c53722 100644 --- a/src/MeoAssistant/Logger.hpp +++ b/src/MeoAssistant/Logger.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "AsstUtils.hpp" #include "Version.h" From 8a5fb6f710f071feba277cf27853ebe768b17dc4 Mon Sep 17 00:00:00 2001 From: zzyyyl <74587068+zzyyyl@users.noreply.github.com> Date: Wed, 11 May 2022 22:32:12 +0800 Subject: [PATCH 04/31] =?UTF-8?q?feat.=E6=9B=B4=E6=96=B0=E8=82=89=E9=B8=BD?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E5=B9=B2=E5=91=98=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resource/combat_recruit.json | 66 +++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/resource/combat_recruit.json b/resource/combat_recruit.json index 597243b9b4..8169abc5c8 100644 --- a/resource/combat_recruit.json +++ b/resource/combat_recruit.json @@ -71,10 +71,6 @@ "subProfession": "pioneer", "position": "MELEE" }, - "预备干员": { - "Doc": "事实上没有叫这个名字的干员,但为了避免肉鸽中,requires设置了但找不到的问题,增设这个干员。", - "level": 3 - }, "翎羽": { "level": 3, "profession": "PIONEER", @@ -297,6 +293,12 @@ "subProfession": "fearless", "position": "MELEE" }, + "断罪者": { + "level": 4, + "profession": "WARRIOR", + "subProfession": "fearless", + "position": "MELEE" + }, "霜叶": { "level": 4, "profession": "WARRIOR", @@ -381,6 +383,12 @@ "subProfession": "healer", "position": "RANGED" }, + "褐果": { + "level": 4, + "profession": "MEDIC", + "subProfession": "wandermedic", + "position": "RANGED" + }, "角峰": { "level": 4, "profession": "TANK", @@ -747,6 +755,12 @@ "subProfession": "funnel", "position": "RANGED" }, + "洛洛": { + "level": 5, + "profession": "CASTER", + "subProfession": "funnel", + "position": "RANGED" + }, "梅尔": { "level": 5, "profession": "SUPPORT", @@ -969,12 +983,24 @@ "subProfession": "slower", "position": "RANGED" }, + "掠风": { + "level": 5, + "profession": "SUPPORT", + "subProfession": "craftsman", + "position": "MELEE" + }, "空": { "level": 5, "profession": "SUPPORT", "subProfession": "bard", "position": "RANGED" }, + "海蒂": { + "level": 5, + "profession": "SUPPORT", + "subProfession": "bard", + "position": "RANGED" + }, "月禾": { "level": 5, "profession": "SUPPORT", @@ -1251,6 +1277,12 @@ "subProfession": "stalker", "position": "MELEE" }, + "归溟幽灵鲨": { + "level": 6, + "profession": "SPECIAL", + "subProfession": "dollkeeper", + "position": "MELEE" + }, "闪灵": { "level": 6, "profession": "MEDIC", @@ -1269,6 +1301,12 @@ "subProfession": "physician", "position": "RANGED" }, + "流明": { + "level": 6, + "profession": "MEDIC", + "subProfession": "healer", + "position": "RANGED" + }, "星熊": { "level": 6, "profession": "TANK", @@ -1305,6 +1343,12 @@ "subProfession": "duelist", "position": "MELEE" }, + "号角": { + "level": 6, + "profession": "TANK", + "subProfession": "fortress", + "position": "MELEE" + }, "山": { "level": 6, "profession": "WARRIOR", @@ -1329,6 +1373,12 @@ "subProfession": "sword", "position": "MELEE" }, + "艾丽妮": { + "level": 6, + "profession": "WARRIOR", + "subProfession": "sword", + "position": "MELEE" + }, "煌": { "level": 6, "profession": "WARRIOR", @@ -1407,10 +1457,8 @@ "subProfession": "fearless", "position": "MELEE" }, - "断罪者": { - "level": 4, - "profession": "WARRIOR", - "subProfession": "fearless", - "position": "MELEE" + "预备干员": { + "Doc": "事实上没有叫这个名字的干员,但为了避免肉鸽中,requires设置了但找不到的问题,增设这个干员。", + "level": 3 } } \ No newline at end of file From 88f87da4dfd9d97a0c4b45209a6d2a436e7a7214 Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 11 May 2022 23:17:34 +0800 Subject: [PATCH 05/31] =?UTF-8?q?feat.=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90?= =?UTF-8?q?4.0=20core=20wpf=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/AbstractImageAnalyzer.cpp | 40 ++++--- src/MeoAssistant/Assistant.cpp | 6 +- src/MeoAsstGui/Helper/AsstProxy.cs | 113 ++++++++++++------ .../ViewModels/TaskQueueViewModel.cs | 8 -- 4 files changed, 102 insertions(+), 65 deletions(-) diff --git a/src/MeoAssistant/AbstractImageAnalyzer.cpp b/src/MeoAssistant/AbstractImageAnalyzer.cpp index e484dbc6db..2ebc71eeb7 100644 --- a/src/MeoAssistant/AbstractImageAnalyzer.cpp +++ b/src/MeoAssistant/AbstractImageAnalyzer.cpp @@ -44,28 +44,30 @@ void asst::AbstractImageAnalyzer::set_roi(const Rect& roi) noexcept asst::Rect asst::AbstractImageAnalyzer::empty_rect_to_full(const Rect& rect, const cv::Mat image) noexcept { + if (image.empty()) { + return rect; + } if (rect.empty()) { return Rect(0, 0, image.cols, image.rows); } - else { - Rect res = rect; - if (image.cols < res.x) { - Log.error("roi is out of range", image.cols, image.rows, res.to_string()); - res.x = image.cols - res.width; - } - if (image.rows < res.y) { - Log.error("roi is out of range", image.cols, image.rows, res.to_string()); - res.y = image.rows - res.height; - } - if (image.cols < res.x + res.width) { - Log.error("roi is out of range", res.to_string()); - res.width = image.cols - res.x; - } - if (image.rows < res.y + res.height) { - Log.error("roi is out of range", res.to_string()); - res.height = image.rows - res.y; - } - return res; + Rect res = rect; + if (image.cols < res.x) { + Log.error("roi is out of range", image.cols, image.rows, res.to_string()); + res.x = image.cols - res.width; } + if (image.rows < res.y) { + Log.error("roi is out of range", image.cols, image.rows, res.to_string()); + res.y = image.rows - res.height; + } + + if (image.cols < res.x + res.width) { + Log.error("roi is out of range", res.to_string()); + res.width = image.cols - res.x; + } + if (image.rows < res.y + res.height) { + Log.error("roi is out of range", res.to_string()); + res.height = image.rows - res.y; + } + return res; } diff --git a/src/MeoAssistant/Assistant.cpp b/src/MeoAssistant/Assistant.cpp index c16757dff0..c8388cde59 100644 --- a/src/MeoAssistant/Assistant.cpp +++ b/src/MeoAssistant/Assistant.cpp @@ -237,7 +237,11 @@ void Assistant::working_proc() bool ret = task_ptr->run(); - m_tasks_list.pop_front(); + lock.lock(); + if (!m_tasks_list.empty()) { + m_tasks_list.pop_front(); + } + lock.unlock(); auto run_msg = AsstMsg::TaskChainCompleted; if (!ret) { diff --git a/src/MeoAsstGui/Helper/AsstProxy.cs b/src/MeoAsstGui/Helper/AsstProxy.cs index 37ff952274..9675974f97 100644 --- a/src/MeoAsstGui/Helper/AsstProxy.cs +++ b/src/MeoAsstGui/Helper/AsstProxy.cs @@ -11,6 +11,7 @@ using System; using System.Runtime.InteropServices; +using System.Text; using System.Windows; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -145,14 +146,13 @@ namespace MeoAsstGui { string taskChain = details["taskchain"].ToString(); - if (taskChain == "RecruitCalc") + if (taskChain == "Recruit") { if (msg == AsstMsg.TaskChainError) { var recruitModel = _container.Get(); recruitModel.RecruitInfo = "识别错误!"; } - return; } var mainModel = _container.Get(); @@ -347,10 +347,9 @@ namespace MeoAsstGui { string taskChain = details["taskchain"].ToString(); - if (taskChain == "RecruitCalc") + if (taskChain == "Recruit") { procRecruitCalcMsg(details); - return; } string what = details["what"].ToString(); @@ -471,7 +470,7 @@ namespace MeoAsstGui { string id = subTaskDetails["id"].ToString(); settings.PenguinId = id; - AsstSetPenguinId(id); + //AsstSetPenguinId(id); } } break; @@ -557,52 +556,108 @@ namespace MeoAsstGui } } + private bool AsstAppendTaskWithEncoding(string type, JObject task_params = null) + { + task_params = task_params ?? new JObject(); + return AsstAppendTask(_handle, type, JsonConvert.SerializeObject(task_params)) != 0; + } + + public static string Utf16ToUtf8(string utf16String) + { + // Get UTF16 bytes and convert UTF16 bytes to UTF8 bytes + byte[] utf16Bytes = Encoding.Unicode.GetBytes(utf16String); + byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, utf16Bytes); + + // Return UTF8 bytes as ANSI string + return Encoding.Default.GetString(utf8Bytes); + } + public bool AsstAppendFight(string stage, int max_medicine, int max_stone, int max_times) { - return true; + var task_params = new JObject(); + task_params["stage"] = stage; + task_params["medicine"] = max_medicine; + task_params["stone"] = max_stone; + task_params["times"] = max_times; + task_params["report_to_penguin"] = true; + var settings = _container.Get(); + task_params["penguin_id"] = settings.PenguinId; + task_params["server"] = "CN"; + return AsstAppendTaskWithEncoding("Fight", task_params); } public bool AsstAppendAward() { - return false; - //return AsstAppendAward(_handle); + return AsstAppendTaskWithEncoding("Award"); } public bool AsstAppendStartUp() { - AsstAppendTask(_handle, "StartUp", "{}"); - return true; - //return AsstAppendStartUp(_handle); + return AsstAppendTaskWithEncoding("StartUp"); } public bool AsstAppendVisit() { - return false; - //return AsstAppendVisit(_handle); + return AsstAppendTaskWithEncoding("Visit"); } public bool AsstAppendMall(bool with_shopping) { - return false; - //return AsstAppendMall(_handle, with_shopping); + var task_params = new JObject(); + task_params["shopping"] = with_shopping; + task_params["shopping_list"] = new JArray { Utf16ToUtf8("碳"), Utf16ToUtf8("家具") }; + task_params["is_black_list"] = true; + return AsstAppendTaskWithEncoding("Mall", task_params); } public bool AsstAppendRecruit(int max_times, int[] select_level, int required_len, int[] confirm_level, int confirm_len, bool need_refresh, bool use_expedited) { - return false; - //return AsstAppendRecruit(_handle, max_times, select_level, required_len, confirm_level, confirm_len, need_refresh, use_expedited); + var task_params = new JObject(); + task_params["refresh"] = need_refresh; + task_params["select"] = new JArray(select_level); + task_params["confirm"] = new JArray(confirm_level); + task_params["times"] = max_times; + task_params["set_time"] = true; + task_params["expedite"] = use_expedited; + task_params["expedite_times"] = max_times; + return AsstAppendTaskWithEncoding("Recruit", task_params); } public bool AsstAppendInfrast(int work_mode, string[] order, int order_len, string uses_of_drones, double dorm_threshold) { - return false; - //return AsstAppendInfrast(_handle, work_mode, order, order_len, uses_of_drones, dorm_threshold); + var task_params = new JObject(); + //task_params["mode"] = 0; + task_params["facility"] = new JArray(order); + task_params["drones"] = uses_of_drones; + task_params["threshold"] = dorm_threshold; + task_params["replenish"] = true; + return AsstAppendTaskWithEncoding("Infrast", task_params); } public bool AsstAppendRoguelike(int mode) { - return false; - //return AsstAppendRoguelike(_handle, mode); + var task_params = new JObject(); + task_params["mode"] = mode; + task_params["opers"] = new JArray { + new JObject { { "name", Utf16ToUtf8("山") }, { "skill", 2 }, { "skill_usage", 2 } }, + new JObject { { "name", Utf16ToUtf8("棘刺") }, { "skill", 3 }, { "skill_usage", 1 } }, + new JObject { { "name", Utf16ToUtf8("芙蓉") }, { "skill", 1 }, { "skill_usage", 1 } }, + new JObject { { "name", Utf16ToUtf8("梓兰") }, { "skill", 1 }, { "skill_usage", 1 } }, + }; + return AsstAppendTaskWithEncoding("Roguelike", task_params); + } + + public bool AsstStartRecruitCalc(int[] select_level, int required_len, bool set_time) + { + var task_params = new JObject(); + task_params["refresh"] = false; + task_params["select"] = new JArray(select_level); + task_params["confirm"] = new JArray(); + task_params["times"] = 0; + task_params["set_time"] = true; + task_params["expedite"] = false; + task_params["expedite_times"] = 0; + return AsstAppendTaskWithEncoding("Recruit", task_params); } public bool AsstStart() @@ -610,26 +665,10 @@ namespace MeoAsstGui return AsstStart(_handle); } - public bool AsstStartRecruitCalc(int[] select_level, int required_len, bool set_time) - { - return false; - //return AsstStartRecruitCalc(_handle, select_level, required_len, set_time); - } - public bool AsstStop() { return AsstStop(_handle); } - - public void AsstSetPenguinId(string id) - { - //AsstSetPenguinId(_handle, id); - } - - //public void AsstSetParam(string type, string param, string value) - //{ - // AsstSetParam(_ptr, type, param, value); - //} } public enum AsstMsg diff --git a/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs b/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs index 70a7d9687c..103c7c009c 100644 --- a/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs +++ b/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs @@ -210,7 +210,6 @@ namespace MeoAsstGui Idle = true; return; } - setPenguinId(); if (Idle) // 一般是点了“停止”按钮了 { @@ -346,13 +345,6 @@ namespace MeoAsstGui return asstProxy.AsstAppendRoguelike(mode); } - private void setPenguinId() - { - var settings = _container.Get(); - var asstProxy = _container.Get(); - asstProxy.AsstSetPenguinId(settings.PenguinId); - } - public void CheckAndShutdown() { if (Shutdown) From 58f6819820241a5afab86c0049bdb5f36f1d12d0 Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 11 May 2022 23:20:55 +0800 Subject: [PATCH 06/31] =?UTF-8?q?fix.=E4=BF=AE=E5=A4=8DSN=E6=B4=BB?= =?UTF-8?q?=E5=8A=A8=E5=85=B3=E5=8D=A1=E5=81=B6=E5=B0=94=E5=8D=A1=E4=BD=8F?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resource/tasks.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/resource/tasks.json b/resource/tasks.json index 2c413ed145..08c2e67a2d 100644 --- a/resource/tasks.json +++ b/resource/tasks.json @@ -44,6 +44,7 @@ "action": "SwipeToTheRight", "next": [ "StageSN-8", + "SNChapter2ToSN-8", "SwipeRightToStageSN-8" ] }, @@ -103,6 +104,7 @@ "action": "SwipeToTheLeft", "next": [ "StageSN-9", + "SNChapter3ToSN-9", "SwipeLeftToStageSN-9" ] }, @@ -162,6 +164,7 @@ "action": "SwipeToTheLeft", "next": [ "StageSN-10", + "SNChapter3ToSN-10", "SwipeLeftToStageSN-10" ] }, From 4ae9c05879a1a7e35fc82cc9d830d0a12cb2669d Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 11 May 2022 23:24:36 +0800 Subject: [PATCH 07/31] =?UTF-8?q?chore.=E5=88=A0=E9=99=A4=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E7=94=A8=E4=B8=8D=E4=B8=8A=E4=BA=86=E7=9A=84=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- appveyor.yml | 24 -- docs/readme.md | 600 ------------------------------------------------- 2 files changed, 624 deletions(-) delete mode 100644 appveyor.yml delete mode 100644 docs/readme.md diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 89b811f78a..0000000000 --- a/appveyor.yml +++ /dev/null @@ -1,24 +0,0 @@ -version: 0.9.{build} -image: Visual Studio 2022 -configuration: -- RelWithDebInfo -- Release -platform: x64 -clone_depth: 1 -before_build: -- ps: nuget restore -build: - project: MeoAssistantArknights.sln - parallel: true - verbosity: minimal -notifications: -- provider: Email - to: - - mistereo@hotmail.com - subject: 'Build {{status}}: {{projectName}} {{buildVersion}}' - message: 'Commit #{{commitId}} by {{commitAuthor}} on {{commitDate}}: {{commitMessage}}' - on_build_success: true - on_build_failure: true - on_build_status_changed: false -on_failure: -- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) diff --git a/docs/readme.md b/docs/readme.md deleted file mode 100644 index dd113830ab..0000000000 --- a/docs/readme.md +++ /dev/null @@ -1,600 +0,0 @@ -# MAA使用说明 - -## 详细介绍 - -### 刷理智 - -- 若选项中没有你需要的关卡,请手动进入游戏 **蓝色开始按钮** 界面,并选择 `当前关卡`。 -- 主界面上的 `吃理智`、`吃石头`、`指定次数` 三个选项为短路开关,即三个选项中的任一条件达到,均会视为任务完成,停止刷理智。 - - 举例1:设置 `吃理智药` : `999`、`吃石头` : `10`、`指定次数` : `1`。则在刷完 **一次** 后,由于满足了 `指定次数`:`1` 的条件,视为任务完成,停止刷理智。 - - 举例2:不勾选 `吃理智药`、不勾选 `吃石头`,设置 `指定次数` : `100`。则在当前可用理智全部刷完后(可能只刷了几次),由于满足了 `不吃理智药`、`不吃石头` 的条件,视为任务完成,停止刷理智。 -- 刷完自动上传 [企鹅物流数据统计](https://penguin-stats.cn/) -- 可自定义企鹅物流 ID -- 识别并显示材料掉落 -- 掉线后会重连,继续刷上次的图 -- 凌晨 4 点刷新后也会重连,继续刷上次的图 -- 支持剿灭模式 -- 支持打完升级了的情况 -- 支持代理失败的情况,会自动放弃本次行动 - -### 基建换班 - -#### 换班策略 - -自动计算并选择 **单设施内的最优解**,支持所有通用类技能和特殊技能组合;支持识别经验书、赤金、原石碎片、芯片,分别使用不同的干员组合! - -#### 宿舍入驻心情阈值 - -识别心情进度条的百分比;心情小于该阈值的干员,不会再去上班,直接进驻宿舍。 - -#### 特殊说明 - -- 基建换班目前均为单设施最优解,但非跨设施的全局最优解。例如:`巫恋+龙舌兰`、`红云+稀音` 等这类单设施内的组合,都是可以正常识别并使用的;`迷迭香`、`红松骑士团` 这类多个设施间联动的体系,暂不支持使用。 -- 若 `无人机用途` 选择 `贸易站-龙门币` ,则将额外识别是否有 `巫恋组`,并优先为其使用。 -- 会客室仅缺一个线索时,会选择对应流派的干员;否则会选择通用干员。 -- 会客室仅当自有线索满时,才会送出线索,并且只送三个。有需要的同学可自行修改 `resource/tasks.json` 中 `SelectClue` - `maxTimes` 字段,自定义送出个数。 -- 控制中枢策略太过复杂,目前只考虑 `阿米娅`、`诗怀雅`、`凯尔希`、`彩虹小队` 及其他心情 +0.05 的干员,后续逐步优化。 -- 部分异格干员会在基建内产生冲突,请留意辅助界面上是否有提示 “干员冲突”,若有请手动再查看下基建换班情况(可能会有某个设施没人) - -### 信用商店随缘买 - -从左到右依次买,但不会买 `碳` 和 `家具零件` 。有需要的同学可自行修改 `resource/tasks.json` 中 `CreditShop-NotToBuy` - `text` 字段,自定义不买的物品。后续版本会尝试开放界面选项 - -### 公开招募识别 - -- 自动公招和公招识别是两个独立的功能! -- 自动公招支持使用 `加急许可`,全自动连续公招!请进入设置中选择~ -- 出 5、6 星都会有弹窗提示 - -### 自动肉鸽功能 - -- 设置中的三个选项 - - 尽可能往后打:用于刷蜡烛 - - 刷源石锭投资,第一层商店后直接退出:刷源石锭最高效的模式,建议手动选择 `古堡观光` (简单)模式 - - 刷源石锭投资,投资后退出:兼顾刷蜡烛和刷源石锭投资的模式 -- 肉鸽使用干员是可以自定义的,默认的干员是作者根据自己的练度随手写的,如果经常作战失败,建议按你自己的练度修改一下,请参考 [肉鸽自定义选人方法](https://github.com/MistEO/MeoAssistantArknights/issues/167)。后期将优化这里的选人逻辑 -- 支持掉线重连、支持凌晨 4 点更新后继续回去刷 -- 如果软件出现 bug 卡住了,会自动放弃当次探索并重试。但如果经常在某个地方卡住然后放弃、严重影响效率的,欢迎提个 issue 反馈一下~ - - -### 其他乱七八糟的说明 - -- 主界面上要执行的任务,是可以拖动改变顺序的。同样设置中基建换班的顺序,也是可以拖动改变的。 -- 新的活动关卡刚上线的时候可能无法正常识别,一般一两天内软件会自动 OTA 更新资源,更新后即可正常识别。 -- 活动关卡掉落识别到的 `未知材料`,一般就是活动商店的票据。 -- `resource/config.json` 中有一些自定义选项,可以尝试根据自己的需要进行修改。 -- 所有点击操作,都是点击按钮内随机位置,并模拟泊松分布(按钮偏中间位置点的概率大,越往旁边点到的概率越小)。 -- 底层算法纯 C++ 开发,并设计了多重的缓存技术,最大限度降低 CPU 和内存占用。 -- 软件支持自动更新✿✿ヽ(°▽°)ノ✿ 推荐非杠精的同学使用测试版,一般来说更新快且 bug 少(什么 MIUI (╯‵□′)╯︵┻━┻ -- 如果新版本自动下载失败,可手动下载后,直接把压缩包放到同目录下,会自动更新的。 - -### 我是国际服玩家,可以使用么? - -可以!但是目前只支持少部分功能,请参考 [这个链接](../resource/international/) - -### I'm an international server player, could I use it? - -Yes, but there are few supported features, please refer to [this link](../resource/international/) -## 模拟器支持 - -### 蓝叠模拟器 - -完美支持。需要在模拟器 `设置` - `引擎设置` 中打开 `允许ADB连接` - -### 蓝叠模拟器国际版(推荐使用) - -完美支持。需要在模拟器 `设定` - `进阶` 中打开 `Android调试桥` - -### 蓝叠模拟器 Hyper-V 版本 - -支持 - -1. 在模拟器 `设定` - `进阶` 中打开 `Android调试桥` -2. 下载 [adb](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) ,将 `platform-tools` 文件夹解压到 `MeoAsstGui.exe` 的同级目录 -3. 在软件 `设置` - `连接设置` 中填写蓝叠安装目录下 `bluestacks.conf` 文件的完整路径 - -### 夜神模拟器 - -完美支持 - -### 夜神模拟器 安卓 9 - -完美支持 - -### MuMu 模拟器 - -支持。但是可能会 - -- 一直连接出错:暂时不知道是什么原因,可尝试使用自定义连接 -- 卡在主界面无法识别,过一会提示任务出错:和 MuMu 的渲染方式有关,推荐换模拟器( - -### MuMu 手游助手(星云引擎) - -不支持。没开放 adb 端口 - -### MuMu 模拟器 安卓 9 - -不支持。adb 截图出来是黑的,不知道怎么整 - -### 雷电模拟器 - -勉强支持。雷电总有莫名其妙的问题,可以试试看,不保证能用( - -### 逍遥模拟器 - -支持。但可能有莫名其妙的识别错误问题 - -### 腾讯手游助手 - -不支持。没开放 adb 端口 - -### Win11 WSA - -不支持。WSA 目前没有实现 AOSP screencap 需要的接口,无法进行截图。等微软支持后会尝试适配 - -### AVD - -支持。 - -### 自定义连接 - -1. 下载 [adb](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) ,将 `platform-tools` 文件夹解压到 `MeoAsstGui.exe` 的同级目录 -2. 进入软件 `设置` - `连接设置`,填写自定义 adb 地址(需要填写 IP + 端口,例如 `127.0.0.1:5555` ) - -**注意 :** 若是使用手机,在非 `16:9` 分辨率下,部分功能不稳定(但也凑合能用),尤其是基建,几乎是不可用状态,正在进一步适配中。推荐使用 `16:9` 分辨率,经过的测试验证最多,也最稳定。 -## 常见问题 - -### 软件一打开就闪退 - -- 可能性 1: 运行库问题。 - 请尝试安装 [Visual C++ Redistributable](https://docs.microsoft.com/zh-CN/cpp/windows/latest-supported-vc-redist?view=msvc-160#visual-studio-2015-2017-2019-and-2022)、[.NET Framework 4.8](https://dotnet.microsoft.com/download/dotnet-framework/net48) 后重新运行本软件。 -- 可能性 2: CPU 指令集不支持。 - 项目使用 `PaddleOCR` 对游戏部分界面进行识别。`PaddleOCR` 用到了较新发布的 CPU 才支持的 `AVX` 指令集,而一些较老的 CPU 可能并不支持该指令集。 - 您可以尝试下载 [NoAVX](../3rdparty/ppocr_noavx.zip) 版本的 `PaddleOCR`, 解压后替换本软件中同名的文件。这是对于使用不支持 `AVX` 指令集的 CPU 的用户的性能降低的替代方案,如非必要,请不要使用。 - (具体可以下载 [CPU-Z](https://www.cpuid.com/softwares/cpu-z.html),查看“指令集”中有无 `AVX` 这一项来判断) -- 若上述均没有效果,请提 issue。 - -### 软件可以正常启动,但一点击开始运行就闪退 - -设置中的`bluestacks.conf`, 是给 [蓝叠模拟器 Hyper-V 版本](https://github.com/MistEO/MeoAssistantArknights/blob/master/docs/%E6%A8%A1%E6%8B%9F%E5%99%A8%E6%94%AF%E6%8C%81.md#%E8%93%9D%E5%8F%A0%E6%A8%A1%E6%8B%9F%E5%99%A8-hyper-v-%E7%89%88%E6%9C%AC) 使用的,若非该版本,请不要填写该项。如果确定不是这个问题,请再提 issue ~ - -### 连接错误/捕获模拟器窗口错误 - -提示 : 请根据 [使用说明](../README.md#使用说明) 确定您的模拟器及打开方式正确 - -- 方法 1: 使用 [自定义连接](#自定义连接) 的方式连接模拟器 -- 方法 2: 换模拟器,推荐 [蓝叠国际版](https://www.bluestacks.com/download.html) Nougat 64 bit -- 方法 3: _根本解决方法_ 编辑 `resource/config.json`, 修改(最好是新增)模拟器窗口句柄名,并修改对应的 adb 设置。若您修改后可以提 PR 给我,我会感激不尽的_(:з」∠)_ - -### 识别错误/任务开始后一直不动、没有反应 - -提示 : 依次进行,若问题解决,则无需往下 - -1. 请根据 [模拟器支持情况](模拟器支持.md) 确定您的模拟器是受支持的 -2. 修改模拟器分辨率设置,`320 dpi` -3. 修改模拟器分辨率设置,横屏 `1280 * 720` 分辨率 -4. 换模拟器,推荐 [蓝叠国际版](https://www.bluestacks.com/download.html) Nougat 64 bit ( 请注意蓝叠需要在模拟器设置里开启 adb ) -5. 若仍有问题,请提 issue - -### 自定义连接 - -- 下载 [adb](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) ,将 `platform-tools` 文件夹解压到 `MeoAsstGui.exe` 的同级目录 -- 进入软件 `设置` - `连接设置`,填写自定义 adb 地址(需要填写 IP + 端口,例如 `127.0.0.1:5555` ) - -### 环境变量中已有 adb, 可以不再下载一份么? - -可以!请手动修改 `resource\config.json` - `Custom` - `adb` - `path` 为 `adb.exe`, 或其他 adb 的路径 -## 回调消息协议 - -### 回调函数原型 - -```c++ -typedef void(ASST_CALL* AsstCallback)(int msg, const char* details, void* custom_arg); -``` - -### 参数总览 - -- `int msg` - 消息类型 - - ```c++ - enum class AsstMsg - { - /* Global Info */ - InternalError = 0, // 内部错误 - InitFailed, // 初始化失败 - ConnectionError, // 连接相关错误 - AllTasksCompleted, // 全部任务完成 - /* TaskChain Info */ - TaskChainError = 10000, // 任务链执行/识别错误 - TaskChainStart, // 任务链开始 - TaskChainCompleted, // 任务链完成 - TaskChainExtraInfo, // 任务链额外信息 - /* SubTask Info */ - SubTaskError = 20000, // 原子任务执行/识别错误 - SubTaskStart, // 原子任务开始 - SubTaskCompleted, // 原子任务完成 - SubTaskExtraInfo // 原子任务额外信息 - }; - ``` - -- `const char* details` - 消息详情,json 字符串,详见 [字段解释](#字段解释) -- `void* custom_arg` - 调用方自定义参数,会原样传出 `AsstCreateEx` 接口中的 `custom_arg` 参数,C 系语言可利用该参数传出 `this` 指针 - -### 字段解释 - -#### InternalError - -Todo - -#### InitFailed - -```jsonc -{ - "what": string, // 错误类型 - "details": object, // 错误详情 -} -``` - -#### ConnectionError - -Todo - -#### AllTasksCompleted - -```jsonc -{ - "taskchain": string, // 最后的任务链 - "pre_taskchain": string // 上一个任务链 -} -``` - -##### 常见 `taskchain` 字段 - -- `StartUp` - 开始唤醒 -- `Fight` - 刷理智 -- `Mall` - 信用点及购物 -- `Recruit` - 自动公招 -- `RecruitCalc` - 公招识别 -- `Infrast` - 基建换班 -- `Roguelike` - 无限刷肉鸽 -- `Debug` - 调试 - -#### TaskChain 相关消息 - -```jsonc -{ - "taskchain": string, // 当前的任务链 - "pre_taskchain": string // 上一个任务链 -} -``` - -#### TaskChainExtraInfo - -Todo - -#### SubTask 相关消息 - -```jsonc -{ - "subtask": string, // 子任务名 - "class": string, // 子任务符号名 - "taskchain": string, // 当前任务链 - "details": object, // 详情 -} -``` - -##### 常见 `subtask` 字段 - -- `ProcessTask` - - ```jsonc - // 对应的 details 字段举例 - { - "task": "StartButton2", // 任务名 - "action": 512, - "exec_times": 1, // 已执行次数 - "max_times": 999, // 最大执行次数 - "algorithm": 0 - } - ``` - -- Todo 其他 - -###### 常见 `task` 字段 - -- `StartButton2` - 开始战斗 -- `MedicineConfirm` - 使用理智药 -- `StoneConfirm` - 碎石 -- `RecruitRefreshConfirm` - 公招刷新标签 -- `RecruitConfirm` - 公招确认招募 -- `RecruitNowConfirm` - 公招使用加急许可 -- `ReportToPenguinStats` - 汇报到企鹅数据统计 -- `InfrastDormDoubleConfirmButton` - 基建宿舍的二次确认按钮,仅当干员冲突时才会有,请提示用户 -- `Roguelike1Start` - 肉鸽开始探索 -- `Roguelike1StageTraderInvestConfirm` - 肉鸽投资了源石锭 -- `Roguelike1StageTraderInvestSystemFull` - 肉鸽投资达到了游戏上限 -- `Roguelike1ExitThenAbandon` - 肉鸽放弃了本次探索 -- `Roguelike1MissionCompletedFlag` - 肉鸽战斗完成 -- `Roguelike1MissionFailedFlag` - 肉鸽战斗失败 -- `Roguelike1StageSafeHouseEnter` - 肉鸽关卡:诡异行商 -- `Roguelike1StageSafeHouseEnter` - 肉鸽关卡:安全的角落 -- `Roguelike1StageEncounterEnter` - 肉鸽关卡:不期而遇/古堡馈赠 -- `Roguelike1StageCambatDpsEnter` - 肉鸽关卡:普通作战 -- `Roguelike1StageEmergencyDps` - 肉鸽关卡:紧急作战 -- `Roguelike1StageDreadfulFoe` - 肉鸽关卡:险路恶敌 -- Todo 其他 - -#### SubTaskExtraInfo - -```jsonc -{ - "taskchain": string, // 当前任务链 - "class": string, // 子任务类型 - "what": string, // 信息类型 - "details": object, // 信息详情 -} -``` - -##### 常见 `what` 及 `details` 字段 - -- `StageDrops` - 关卡材料掉落信息 - - ```jsonc - // 对应的 details 字段举例 - { - "exceptions": [], - "resultLabel": true, - "drops": [ // 本次识别到的掉落材料 - { - "dropType": "NORMAL_DROP", - "itemId": "3301", - "quantity": 2, - "itemName": "技巧概要·卷1" - }, - { - "dropType": "NORMAL_DROP", - "itemId": "3302", - "quantity": 1, - "itemName": "技巧概要·卷2" - }, - { - "dropType": "NORMAL_DROP", - "itemId": "3303", - "quantity": 2, - "itemName": "技巧概要·卷3" - } - ], - "dropTypes": [ - { - "dropTypes": "LMB" - }, - { - "dropTypes": "NORMAL_DROP" - } - ], - "stage": { // 关卡信息 - "stageCode": "CA-5", - "stageId": "wk_fly_5" - }, - "stars": 3, // 行动结束星级 - "fingerprint": "e464bafaa3f92877bbc4fb20209e4169ae49d587499c8d2e72026b96356c591f6a17477a5b345518a00b23be78252e0825070585d33f2109390807672c252a0b", - "md5": "b40ea51ec7802afa2e86951bffbbc21f", - "cost": 6.0624, - "stats": [ // 本次执行期间总的材料掉落 - { - "itemId": "3301", - "itemName": "技巧概要·卷1", - "quantity": 4 - }, - { - "itemId": "3302", - "itemName": "技巧概要·卷2", - "quantity": 3 - }, - { - "itemId": "3303", - "itemName": "技巧概要·卷3", - "quantity": 4 - } - ] - } - ``` - -- `RecruitTagsDetected` - 公招识别到了 Tags - - ```jsonc - // 对应的 details 字段举例 - { - "tags": [ - "费用回复", - "防护", - "先锋干员", - "辅助干员", - "近战位" - ] - } - ``` - -- `RecruitSpecialTag` - 公招识别到了特殊 Tag - - ```jsonc - // 对应的 details 字段举例 - { - "tag": "高级资深干员" - } - ``` - -- `RecruitResult` - 公招识别结果 - - ```jsonc - // 对应的 details 字段举例 - { - "level": 4, // 总的星级 - "result": [ - { - "tags": [ - "削弱" - ], - "level": 4, // 这组 tags 的星级 - "opers": [ - { - "name": "初雪", - "level": 5 // 干员星级 - }, - { - "name": "陨星", - "level": 5 - }, - { - "name": "槐琥", - "level": 5 - }, - { - "name": "夜烟", - "level": 4 - }, - { - "name": "流星", - "level": 4 - } - ] - }, - { - "tags": [ - "减速", - "术师干员" - ], - "level": 4, - "opers": [ - { - "name": "夜魔", - "level": 5 - }, - { - "name": "格雷伊", - "level": 4 - } - ] - }, - { - "tags": [ - "削弱", - "术师干员" - ], - "level": 4, - "opers": [ - { - "name": "夜烟", - "level": 4 - } - ] - } - ] - } - ``` - -- `RecruitTagsSelected` - 公招选择了 Tags - - ```jsonc - // 对应的 details 字段举例 - { - "tags": [ - "减速", - "术师干员" - ] - } - ``` - -- `EnterFacility` - 基建进入了设施 - - ```jsonc - // 对应的 details 字段举例 - { - "facility": "Mfg", // 设施名 - "index": 0 // 设施序号 - } - ``` - -- `NotEnoughStaff` - 基建可用干员不足 - - ```jsonc - // 对应的 details 字段举例 - { - "facility": "Mfg", // 设施名 - "index": 0 // 设施序号 - } - ``` - -- `ProductOfFacility` - 基建产物 - - ```jsonc - // 对应的 details 字段举例 - { - "product": "Money", // 产物名 - "facility": "Mfg", // 设施名 - "index": 0 // 设施序号 - } - ``` - -- `StageInfo` - 自动作战关卡信息 - - ```jsonc - // 对应的 details 字段举例 - { - "name": string // 关卡名 - } - ``` - -- `StageInfoError` - 自动作战关卡识别错误 - -- `PenguinId` - 企鹅物流 ID - - ```jsonc - // 对应的 details 字段举例 - { - "id": string - } - ``` - From 7044c48e1a561501009fd0e8ffefef78a6e86c4a Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 11 May 2022 23:31:24 +0800 Subject: [PATCH 08/31] chore. disable a warning --- src/MeoAssistant/Controller.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index 02f1a77af6..2ecef395c9 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -16,7 +16,11 @@ #include #include + +#pragma warning( push ) +#pragma warning( disable : 4068) #include +#pragma warning( pop ) #include "AsstTypes.h" #include "Logger.hpp" From d25348e9bb851b83c405e6cdbe73425675758838 Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 11 May 2022 23:44:23 +0800 Subject: [PATCH 09/31] =?UTF-8?q?docs.=E4=BF=AE=E5=A4=8D=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/战斗流程协议.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/战斗流程协议.md b/docs/战斗流程协议.md index 7b9c5c3491..a2f8094b7d 100644 --- a/docs/战斗流程协议.md +++ b/docs/战斗流程协议.md @@ -105,5 +105,5 @@ ## 举例 -[Sample](../resource/battle/test.json) -[GA-EX8 突袭作业](../resource/battle/GA-EX8-raid.json) +[Sample](../resource/copilot/test.json) +[GA-EX8 突袭作业](../resource/copilot/GA-EX8-raid.json) From 1aafd343ec994418c65f8fb138bb35a6af3324f6 Mon Sep 17 00:00:00 2001 From: bakashigure Date: Thu, 12 May 2022 11:17:47 +0800 Subject: [PATCH 10/31] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9uuid=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resource/config.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/resource/config.json b/resource/config.json index 79d48f64c1..41b0862d77 100644 --- a/resource/config.json +++ b/resource/config.json @@ -24,7 +24,7 @@ "devices": "[Adb] devices", "addressRegex": "(.+)\tdevice", "connect": "[Adb] connect [Address]", - "uuid": "[Adb] -s [Address] shell settings get secure android_id", + "uuid": "[Adb] -s [Address] shell \"settings get secure android_id | awk 'NR == 1 {p = $0} NR > 1 {print p; p = $0} END{printf p}' \"", "click": "[Adb] -s [Address] shell input tap [x] [y]", "swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]", "display": "[Adb] -s [Address] shell dumpsys window displays | grep init=", @@ -37,7 +37,7 @@ "devices": "[Adb] devices", "addressRegex": "(.+)\tdevice", "connect": "[Adb] connect [Address]", - "uuid": "[Adb] -s [Address] shell settings get secure android_id", + "uuid": "[Adb] -s [Address] shell \"settings get secure android_id | awk 'NR == 1 {p = $0} NR > 1 {print p; p = $0} END{printf p}' \"", "click": "[Adb] -s [Address] shell input tap [x] [y]", "swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]", "display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '", @@ -50,7 +50,7 @@ "devices": "[Adb] devices", "addressRegex": "(.+)\tdevice", "connect": "[Adb] connect [Address]", - "uuid": "[Adb] -s [Address] shell settings get secure android_id", + "uuid": "[Adb] -s [Address] shell \"settings get secure android_id | awk 'NR == 1 {p = $0} NR > 1 {print p; p = $0} END{printf p}' \"", "click": "[Adb] -s [Address] shell input tap [x] [y]", "swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]", "display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '", @@ -63,7 +63,7 @@ "devices": "[Adb] devices", "addressRegex": "(.+)\tdevice", "connect": "[Adb] connect [Address]", - "uuid": "[Adb] -s [Address] shell settings get secure android_id", + "uuid": "[Adb] -s [Address] shell \"settings get secure android_id | awk 'NR == 1 {p = $0} NR > 1 {print p; p = $0} END{printf p}' \"", "click": "[Adb] -s [Address] shell input tap [x] [y]", "swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]", "display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '", @@ -76,7 +76,7 @@ "devices": "[Adb] devices", "addressRegex": "(.+)\tdevice", "connect": "[Adb] connect [Address]", - "uuid": "[Adb] -s [Address] shell settings get secure android_id", + "uuid": "[Adb] -s [Address] shell \"settings get secure android_id | awk 'NR == 1 {p = $0} NR > 1 {print p; p = $0} END{printf p}' \"", "click": "[Adb] -s [Address] shell input tap [x] [y]", "swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]", "display": "[Adb] -s [Address] shell dumpsys window displays | grep init= | awk ' { print $3 } '", @@ -89,7 +89,7 @@ "devices": "[Adb] devices", "addressRegex": "(.+)\tdevice", "connect": "[Adb] connect [Address]", - "uuid": "[Adb] -s [Address] shell settings get secure android_id", + "uuid": "[Adb] -s [Address] shell \"settings get secure android_id | awk 'NR == 1 {p = $0} NR > 1 {print p; p = $0} END{printf p}' \"", "click": "[Adb] -s [Address] shell input tap [x] [y]", "swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]", "display": "[Adb] -s [Address] shell dumpsys window displays | grep init=", @@ -103,7 +103,7 @@ "addressRegex": "(.+)\tdevice", "connect": "[Adb] connect [Address]", "displayId": "[Adb] -s [Address] shell dumpsys display | grep mUniqueId=virtual:com.microsoft.windows.systemapp:com.hypergryph.arknights", - "uuid": "[Adb] -s [Address] shell settings get secure android_id", + "uuid": "[Adb] -s [Address] shell \"settings get secure android_id | awk 'NR == 1 {p = $0} NR > 1 {print p; p = $0} END{printf p}' \"", "click": "[Adb] -s [Address] shell input -d [DisplayId] tap [x] [y]", "swipe": "[Adb] -s [Address] shell input -d [DisplayId] swipe [x1] [y1] [x2] [y2] [duration]", "display": "[Adb] -s [Address] shell \"wm size -d [DisplayId]\"", From 611a84d4cfe5056280b16d673eb2988ff1aa50ce Mon Sep 17 00:00:00 2001 From: Alex Zhang Date: Fri, 13 May 2022 11:41:22 +0800 Subject: [PATCH 11/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86dart=20interfa?= =?UTF-8?q?ce=20(=E4=BD=86=E6=90=9E=E4=B8=8D=E5=AE=9A=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E5=BA=93)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dart/.gitignore | 33 + src/dart/.metadata | 10 + src/dart/CHANGELOG.md | 3 + src/dart/LICENSE | 1 + src/dart/README.md | 15 + src/dart/analysis_options.yaml | 4 + src/dart/example/.gitignore | 46 + src/dart/example/.metadata | 10 + src/dart/example/README.md | 16 + src/dart/example/analysis_options.yaml | 29 + src/dart/example/lib/main.dart | 96 + src/dart/example/linux/.gitignore | 1 + src/dart/example/linux/CMakeLists.txt | 116 + src/dart/example/linux/flutter/CMakeLists.txt | 87 + .../flutter/generated_plugin_registrant.cc | 15 + .../flutter/generated_plugin_registrant.h | 15 + .../linux/flutter/generated_plugins.cmake | 16 + src/dart/example/linux/main.cc | 6 + src/dart/example/linux/my_application.cc | 104 + src/dart/example/linux/my_application.h | 18 + src/dart/example/pubspec.lock | 189 + src/dart/example/pubspec.yaml | 93 + src/dart/example/test/widget_test.dart | 30 + src/dart/lib/maa_core.dart | 153 + src/dart/lib/typedefs.dart | 86 + src/dart/linux/CMakeLists.txt | 31 + .../linux/include/maa_core/maa_core_plugin.h | 26 + src/dart/linux/maa_core_plugin.cc | 70 + src/dart/native/CMakeLists.txt | 27 + src/dart/native/dart/dart_api.h | 4016 +++++++++++++++++ src/dart/native/dart/dart_api_dl.c | 59 + src/dart/native/dart/dart_api_dl.h | 150 + src/dart/native/dart/dart_native_api.h | 197 + src/dart/native/dart/dart_tools_api.h | 538 +++ src/dart/native/dart/dart_version.h | 16 + .../native/dart/internal/dart_api_dl_impl.h | 21 + src/dart/native/include/AsstDartApi.h | 9 + src/dart/native/src/AsstDartApi.cpp | 42 + src/dart/pubspec.yaml | 63 + 39 files changed, 6457 insertions(+) create mode 100644 src/dart/.gitignore create mode 100644 src/dart/.metadata create mode 100644 src/dart/CHANGELOG.md create mode 100644 src/dart/LICENSE create mode 100644 src/dart/README.md create mode 100644 src/dart/analysis_options.yaml create mode 100644 src/dart/example/.gitignore create mode 100644 src/dart/example/.metadata create mode 100644 src/dart/example/README.md create mode 100644 src/dart/example/analysis_options.yaml create mode 100644 src/dart/example/lib/main.dart create mode 100644 src/dart/example/linux/.gitignore create mode 100644 src/dart/example/linux/CMakeLists.txt create mode 100644 src/dart/example/linux/flutter/CMakeLists.txt create mode 100644 src/dart/example/linux/flutter/generated_plugin_registrant.cc create mode 100644 src/dart/example/linux/flutter/generated_plugin_registrant.h create mode 100644 src/dart/example/linux/flutter/generated_plugins.cmake create mode 100644 src/dart/example/linux/main.cc create mode 100644 src/dart/example/linux/my_application.cc create mode 100644 src/dart/example/linux/my_application.h create mode 100644 src/dart/example/pubspec.lock create mode 100644 src/dart/example/pubspec.yaml create mode 100644 src/dart/example/test/widget_test.dart create mode 100644 src/dart/lib/maa_core.dart create mode 100644 src/dart/lib/typedefs.dart create mode 100644 src/dart/linux/CMakeLists.txt create mode 100644 src/dart/linux/include/maa_core/maa_core_plugin.h create mode 100644 src/dart/linux/maa_core_plugin.cc create mode 100644 src/dart/native/CMakeLists.txt create mode 100644 src/dart/native/dart/dart_api.h create mode 100644 src/dart/native/dart/dart_api_dl.c create mode 100644 src/dart/native/dart/dart_api_dl.h create mode 100644 src/dart/native/dart/dart_native_api.h create mode 100644 src/dart/native/dart/dart_tools_api.h create mode 100644 src/dart/native/dart/dart_version.h create mode 100644 src/dart/native/dart/internal/dart_api_dl_impl.h create mode 100644 src/dart/native/include/AsstDartApi.h create mode 100644 src/dart/native/src/AsstDartApi.cpp create mode 100644 src/dart/pubspec.yaml diff --git a/src/dart/.gitignore b/src/dart/.gitignore new file mode 100644 index 0000000000..18634e2fef --- /dev/null +++ b/src/dart/.gitignore @@ -0,0 +1,33 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ +*.so +build/ +native/build/ +libraries/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/src/dart/.metadata b/src/dart/.metadata new file mode 100644 index 0000000000..db9312a7b7 --- /dev/null +++ b/src/dart/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 5464c5bac742001448fe4fc0597be939379f88ea + channel: stable + +project_type: plugin diff --git a/src/dart/CHANGELOG.md b/src/dart/CHANGELOG.md new file mode 100644 index 0000000000..41cc7d8192 --- /dev/null +++ b/src/dart/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/src/dart/LICENSE b/src/dart/LICENSE new file mode 100644 index 0000000000..ba75c69f7f --- /dev/null +++ b/src/dart/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/src/dart/README.md b/src/dart/README.md new file mode 100644 index 0000000000..70353da467 --- /dev/null +++ b/src/dart/README.md @@ -0,0 +1,15 @@ +# maa_core + +A new flutter plugin project. + +## Getting Started + +This project is a starting point for a Flutter +[plug-in package](https://flutter.dev/developing-packages/), +a specialized package that includes platform-specific implementation code for +Android and/or iOS. + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. + diff --git a/src/dart/analysis_options.yaml b/src/dart/analysis_options.yaml new file mode 100644 index 0000000000..a5744c1cfb --- /dev/null +++ b/src/dart/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/src/dart/example/.gitignore b/src/dart/example/.gitignore new file mode 100644 index 0000000000..0fa6b675c0 --- /dev/null +++ b/src/dart/example/.gitignore @@ -0,0 +1,46 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/src/dart/example/.metadata b/src/dart/example/.metadata new file mode 100644 index 0000000000..3c3e4b52f7 --- /dev/null +++ b/src/dart/example/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 5464c5bac742001448fe4fc0597be939379f88ea + channel: stable + +project_type: app diff --git a/src/dart/example/README.md b/src/dart/example/README.md new file mode 100644 index 0000000000..a135626028 --- /dev/null +++ b/src/dart/example/README.md @@ -0,0 +1,16 @@ +# example + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/src/dart/example/analysis_options.yaml b/src/dart/example/analysis_options.yaml new file mode 100644 index 0000000000..61b6c4de17 --- /dev/null +++ b/src/dart/example/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/src/dart/example/lib/main.dart b/src/dart/example/lib/main.dart new file mode 100644 index 0000000000..b95ada0972 --- /dev/null +++ b/src/dart/example/lib/main.dart @@ -0,0 +1,96 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'dart:ffi'; +import 'package:ffi/ffi.dart'; +import "package:maa_core/maa_core.dart"; +import 'package:maa_core/typedefs.dart'; +import "package:path/path.dart" as p; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + // This is the theme of your application. + // + // Try running your application with "flutter run". You'll see the + // application has a blue toolbar. Then, without quitting the app, try + // changing the primarySwatch below to Colors.green and then invoke + // "hot reload" (press "r" in the console where you ran "flutter run", + // or simply save your changes to "hot reload" in a Flutter IDE). + // Notice that the counter didn't reset back to zero; the application + // is not restarted. + primarySwatch: Colors.blue, + ), + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({Key? key, required this.title}) : super(key: key); + + // This widget is the home page of your application. It is stateful, meaning + // that it has a State object (defined below) that contains fields that affect + // how it looks. + + // This class is the configuration for the state. It holds the values (in this + // case the title) provided by the parent (in this case the App widget) and + // used by the build method of the State. Fields in a Widget subclass are + // always marked "final". + + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + late MaaCore _asst; + List _logs =[]; + + @override + void initState() { + setState(() { + _asst = MaaCore(p.join(p.current, 'linux')); + }); + super.initState(); + } + void callback(dynamic message) { + setState(() { + _logs.add(message); + }); + } + + @override + Widget build(BuildContext context) { + // This method is rerun every time setState is called, for instance as done + // by the _incrementCounter method above. + // + // The Flutter framework has been optimized to make rerunning build methods + // fast, so that you can just rebuild anything that needs updating rather + // than having to individually change instances of widgets. + + return Scaffold( + appBar: AppBar( + // Here we take the value from the MyHomePage object that was created by + // the App.build method, and use it to set our appbar title. + title: Text(widget.title), + ), + body: Center( + child: Column( + children: _logs.map((e) => Text(e)).toList(), + ), + ) + ); + } +} diff --git a/src/dart/example/linux/.gitignore b/src/dart/example/linux/.gitignore new file mode 100644 index 0000000000..d3896c9844 --- /dev/null +++ b/src/dart/example/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/src/dart/example/linux/CMakeLists.txt b/src/dart/example/linux/CMakeLists.txt new file mode 100644 index 0000000000..a558bc458a --- /dev/null +++ b/src/dart/example/linux/CMakeLists.txt @@ -0,0 +1,116 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "example") +set(APPLICATION_ID "com.example.example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/src/dart/example/linux/flutter/CMakeLists.txt b/src/dart/example/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000000..33fd5801e7 --- /dev/null +++ b/src/dart/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,87 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/src/dart/example/linux/flutter/generated_plugin_registrant.cc b/src/dart/example/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000000..b133bd07b0 --- /dev/null +++ b/src/dart/example/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include + +void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) maa_core_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "MaaCorePlugin"); + maa_core_plugin_register_with_registrar(maa_core_registrar); +} diff --git a/src/dart/example/linux/flutter/generated_plugin_registrant.h b/src/dart/example/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000000..e0f0a47bc0 --- /dev/null +++ b/src/dart/example/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/src/dart/example/linux/flutter/generated_plugins.cmake b/src/dart/example/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000000..55b005231e --- /dev/null +++ b/src/dart/example/linux/flutter/generated_plugins.cmake @@ -0,0 +1,16 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + maa_core +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) diff --git a/src/dart/example/linux/main.cc b/src/dart/example/linux/main.cc new file mode 100644 index 0000000000..e7c5c54370 --- /dev/null +++ b/src/dart/example/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/src/dart/example/linux/my_application.cc b/src/dart/example/linux/my_application.cc new file mode 100644 index 0000000000..0ba8f43096 --- /dev/null +++ b/src/dart/example/linux/my_application.cc @@ -0,0 +1,104 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "example"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/src/dart/example/linux/my_application.h b/src/dart/example/linux/my_application.h new file mode 100644 index 0000000000..72271d5e41 --- /dev/null +++ b/src/dart/example/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/src/dart/example/pubspec.lock b/src/dart/example/pubspec.lock new file mode 100644 index 0000000000..8cf32ef184 --- /dev/null +++ b/src/dart/example/pubspec.lock @@ -0,0 +1,189 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.8.2" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.15.0" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + ffi: + dependency: "direct main" + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + lints: + dependency: transitive + description: + name: lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + maa_core: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "0.0.1" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.0" + path: + dependency: "direct main" + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.8" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" +sdks: + dart: ">=2.16.2 <3.0.0" + flutter: ">=2.5.0" diff --git a/src/dart/example/pubspec.yaml b/src/dart/example/pubspec.yaml new file mode 100644 index 0000000000..7f58353e20 --- /dev/null +++ b/src/dart/example/pubspec.yaml @@ -0,0 +1,93 @@ +name: example +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 + +environment: + sdk: ">=2.16.2 <3.0.0" + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + maa_core: + path: ../ + ffi: + path: + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^1.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/src/dart/example/test/widget_test.dart b/src/dart/example/test/widget_test.dart new file mode 100644 index 0000000000..a19dabb076 --- /dev/null +++ b/src/dart/example/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:example/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/src/dart/lib/maa_core.dart b/src/dart/lib/maa_core.dart new file mode 100644 index 0000000000..ea63a26810 --- /dev/null +++ b/src/dart/lib/maa_core.dart @@ -0,0 +1,153 @@ +import 'dart:ffi'; +import 'dart:convert'; +import 'dart:isolate'; +import 'package:ffi/ffi.dart'; +import 'package:maa_core/typedefs.dart'; +import 'package:path/path.dart' as p; + +class MaaCore implements MaaCoreInterface { + late Assistant _asst; + late AsstConnectFunc _asstConnect; + late AsstDestroyFunc _asstDestroy; + late AsstAppendTaskFunc _asstAppendTask; + late AsstSetTaskParamsFunc _asstSetTaskParams; + late AsstStartFunc _asstStart; + late AsstStopFunc _asstStop; + late AsstCtrlerClickFunc _asstCtrlerClick; + late AsstGetVersionFunc _asstGetVersion; + late AsstLogFunc _asstLog; + static bool resourceLoaded = false; + late ReceivePort? _receivePort; + ReceivePort? get receivePort => _receivePort; + late Pointer _pointer; + static Future get platformVersion async { + return Future(() => '0.0.1'); + } + + static bool loadResource(DynamicLibrary lib, String resourceDir) { + final AsstLoadResourceFunc asstLoadResource = + lib.lookup('AsstLoadResource').asFunction(); + if (!resourceLoaded) { + return asstLoadResource(resourceDir.toNativeUtf8()); + } + return true; + } + + MaaCore(String libDir, [Function(dynamic)? callback]) { + + _loadCppLib(libDir); + final _createWithDartPort = loadAsstCreateDart(libDir); + _receivePort = ReceivePort(); + final portPtr = malloc.allocate(sizeOf()); + portPtr.value = _receivePort!.sendPort.nativePort; + _asst = _createWithDartPort(portPtr); + if (callback != null) { + _receivePort!.listen(callback); + } + } + + void _loadCppLib(String libDir) { + final lib = DynamicLibrary.open(p.join(libDir, 'libMeoAssistant.so')); + + _asstConnect = lib.lookup('AsstConnect').asFunction(); + _asstDestroy = lib.lookup('AsstDestroy').asFunction(); + _asstAppendTask = + lib.lookup('AsstAppendTask').asFunction(); + _asstSetTaskParams = + lib.lookup('AsstSetTaskParams').asFunction(); + _asstStart = lib.lookup('AsstStart').asFunction(); + _asstStop = lib.lookup('AsstStop').asFunction(); + _asstCtrlerClick = + lib.lookup('AsstCtrlerClick').asFunction(); + _asstGetVersion = + lib.lookup('AsstGetVersion').asFunction(); + _asstLog = lib.lookup('AsstLog').asFunction(); + } + + @override + bool connect({ + required String adbPath, + required String address, + String config = '', + }) { + return _asstConnect( + _asst, + adbPath.toNativeUtf8(), + address.toNativeUtf8(), + config.toNativeUtf8(), + ); + } + + @override + void destroy() { + if (_receivePort != null) { + _receivePort!.close(); + malloc.free(_pointer); + } + _asstDestroy(_asst); + } + + @override + TaskId appendTask(String type, [Map? params]) { + final json = jsonEncode(params ?? {}); + final taskId = _asstAppendTask( + _asst, + type.toNativeUtf8(), + json.toNativeUtf8(), + ); + return taskId; + } + + @override + bool setTaskParams(TaskId taskId, [Map? params]) { + final json = jsonEncode(params); + final result = _asstSetTaskParams( + _asst, + taskId, + json.toNativeUtf8(), + ); + return result; + } + + @override + bool start() { + return _asstStart(_asst); + } + + @override + bool stop() { + return _asstStop(_asst); + } + + @override + bool ctrlerClick({required int x, required int y, required block}) { + return _asstCtrlerClick(_asst, x, y, block); + } + + @override + String getVersion() { + return _asstGetVersion().toDartString(); + } + + @override + void log(String logLevel, String msg) { + _asstLog(logLevel.toNativeUtf8(), msg.toNativeUtf8()); + } +} + +AsstCreateDartFunc loadAsstCreateDart(String libPath) { + final lib = DynamicLibrary.open(p.join(libPath, 'libMeoAssistantDart.so')); + return lib + .lookup('AsstCreateWithDartPort') + .asFunction(); +} + +InitDartVMFunc loadInitDartVM(String libPath) { + final lib = DynamicLibrary.open(p.join(libPath, 'libMeoAssistantDart.so')); + return lib.lookup('InitDartVM').asFunction(); +} + +CleanUpDartVMFunc loadCleanUpDartVM(String libPath) { + final lib = DynamicLibrary.open(p.join(libPath, 'libMeoAssistantDart.so')); + return lib.lookup('CleanUpDartVM').asFunction(); +} diff --git a/src/dart/lib/typedefs.dart b/src/dart/lib/typedefs.dart new file mode 100644 index 0000000000..d3e6fac7d9 --- /dev/null +++ b/src/dart/lib/typedefs.dart @@ -0,0 +1,86 @@ +import "dart:ffi"; + +import "package:ffi/ffi.dart"; + +typedef Assistant = Pointer; +typedef AsstCallbackNative + = NativeFunction)>; + +typedef AsstCallbackFunc = Void Function(Int32, StringPtr, Pointer); +// AsstCreateEx +typedef AsstCreateDartFunc = Assistant Function(Pointer); +typedef AsstCreateDartNative + = NativeFunction)>; + +// AsstCreate +typedef AsstCreateFunc = Assistant Function(); +typedef AsstCreateNative = NativeFunction; + +// AsstDestroy +typedef AsstDestroyFunc = void Function(Assistant); +typedef AsstDestroyNative = NativeFunction; + +// AsstConnect +typedef AsstConnectFunc = bool Function( + Assistant, StringPtr, StringPtr, StringPtr); +typedef AsstConnectNative + = NativeFunction; + +// AsstAppendTask +typedef AsstAppendTaskFunc = TaskId Function(Assistant, StringPtr, StringPtr); +typedef AsstAppendTaskNative + = NativeFunction; + +// AsstSetTaskParams +typedef AsstSetTaskParamsFunc = bool Function(Assistant, TaskId, StringPtr); +typedef AsstSetTaskParamsNative + = NativeFunction; + +// AsstStart +typedef AsstStartFunc = bool Function(Assistant); +typedef AsstStartNative = NativeFunction; + +// AsstStop +typedef AsstStopFunc = bool Function(Assistant); +typedef AsstStopNative = NativeFunction; + +// AsstCtrlerClick +typedef AsstCtrlerClickFunc = bool Function(Assistant, int, int, bool); +typedef AsstCtrlerClickNative + = NativeFunction; + +// AsstGetVersion +typedef AsstGetVersionFunc = StringPtr Function(); +typedef AsstGetVersionNative = NativeFunction; + +// AsstLog +typedef AsstLogFunc = void Function(StringPtr, StringPtr); +typedef AsstLogNative = NativeFunction; + +// AsstLoadResource +typedef AsstLoadResourceFunc = bool Function(StringPtr); +typedef AsstLoadResourceNative = NativeFunction; + +typedef TaskId = int; +typedef TaskIdNative = Int32; +typedef StringPtr = Pointer; + +typedef InitDartVMFunc = void Function(Pointer); +typedef InitDartVMNative = NativeFunction)>; + + +typedef CleanUpDartVMFunc = void Function(); +typedef CleanUpDartVMNative = NativeFunction; + +abstract class MaaCoreInterface { + void destroy(); + bool connect( + {required String adbPath, required String address, String config = ''}); + TaskId appendTask(String type, [Map? params]); + bool setTaskParams(TaskId taskId, [Map? params]); + bool start(); + bool stop(); + bool ctrlerClick({required int x, required int y, required block}); + void log(String logLevel, String msg); + String getVersion(); +} diff --git a/src/dart/linux/CMakeLists.txt b/src/dart/linux/CMakeLists.txt new file mode 100644 index 0000000000..709b37baef --- /dev/null +++ b/src/dart/linux/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.10) +set(PROJECT_NAME "maa_core") +project(${PROJECT_NAME} LANGUAGES CXX) + +# This value is used when generating builds using this plugin, so it must +# not be changed +set(PLUGIN_NAME "maa_core_plugin") + + + +add_library(${PLUGIN_NAME} SHARED + "maa_core_plugin.cc" +) + +apply_standard_settings(${PLUGIN_NAME}) +set_target_properties(${PLUGIN_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) + +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include" +) + +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) +target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) + +# List of absolute paths to libraries that should be bundled with the plugin +set(maa_core_bundled_libraries + "" + PARENT_SCOPE +) diff --git a/src/dart/linux/include/maa_core/maa_core_plugin.h b/src/dart/linux/include/maa_core/maa_core_plugin.h new file mode 100644 index 0000000000..90c8d01e6f --- /dev/null +++ b/src/dart/linux/include/maa_core/maa_core_plugin.h @@ -0,0 +1,26 @@ +#ifndef FLUTTER_PLUGIN_MAA_CORE_PLUGIN_H_ +#define FLUTTER_PLUGIN_MAA_CORE_PLUGIN_H_ + +#include + +G_BEGIN_DECLS + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) +#else +#define FLUTTER_PLUGIN_EXPORT +#endif + +typedef struct _MaaCorePlugin MaaCorePlugin; +typedef struct { + GObjectClass parent_class; +} MaaCorePluginClass; + +FLUTTER_PLUGIN_EXPORT GType maa_core_plugin_get_type(); + +FLUTTER_PLUGIN_EXPORT void maa_core_plugin_register_with_registrar( + FlPluginRegistrar* registrar); + +G_END_DECLS + +#endif // FLUTTER_PLUGIN_MAA_CORE_PLUGIN_H_ diff --git a/src/dart/linux/maa_core_plugin.cc b/src/dart/linux/maa_core_plugin.cc new file mode 100644 index 0000000000..2fd43789c1 --- /dev/null +++ b/src/dart/linux/maa_core_plugin.cc @@ -0,0 +1,70 @@ +#include "include/maa_core/maa_core_plugin.h" + +#include +#include +#include + +#include + +#define MAA_CORE_PLUGIN(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), maa_core_plugin_get_type(), \ + MaaCorePlugin)) + +struct _MaaCorePlugin { + GObject parent_instance; +}; + +G_DEFINE_TYPE(MaaCorePlugin, maa_core_plugin, g_object_get_type()) + +// Called when a method call is received from Flutter. +static void maa_core_plugin_handle_method_call( + MaaCorePlugin* self, + FlMethodCall* method_call) { + g_autoptr(FlMethodResponse) response = nullptr; + + const gchar* method = fl_method_call_get_name(method_call); + + if (strcmp(method, "getPlatformVersion") == 0) { + struct utsname uname_data = {}; + uname(&uname_data); + g_autofree gchar *version = g_strdup_printf("Linux %s", uname_data.version); + g_autoptr(FlValue) result = fl_value_new_string(version); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + } else { + response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new()); + } + + fl_method_call_respond(method_call, response, nullptr); +} + +static void maa_core_plugin_dispose(GObject* object) { + G_OBJECT_CLASS(maa_core_plugin_parent_class)->dispose(object); +} + +static void maa_core_plugin_class_init(MaaCorePluginClass* klass) { + G_OBJECT_CLASS(klass)->dispose = maa_core_plugin_dispose; +} + +static void maa_core_plugin_init(MaaCorePlugin* self) {} + +static void method_call_cb(FlMethodChannel* channel, FlMethodCall* method_call, + gpointer user_data) { + MaaCorePlugin* plugin = MAA_CORE_PLUGIN(user_data); + maa_core_plugin_handle_method_call(plugin, method_call); +} + +void maa_core_plugin_register_with_registrar(FlPluginRegistrar* registrar) { + MaaCorePlugin* plugin = MAA_CORE_PLUGIN( + g_object_new(maa_core_plugin_get_type(), nullptr)); + + g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); + g_autoptr(FlMethodChannel) channel = + fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar), + "maa_core", + FL_METHOD_CODEC(codec)); + fl_method_channel_set_method_call_handler(channel, method_call_cb, + g_object_ref(plugin), + g_object_unref); + + g_object_unref(plugin); +} diff --git a/src/dart/native/CMakeLists.txt b/src/dart/native/CMakeLists.txt new file mode 100644 index 0000000000..0380552352 --- /dev/null +++ b/src/dart/native/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 2.8) +project(MeoAssistantArknightsDart) + +if (WIN32) + add_compile_options("$<$:/utf-8>") + add_compile_options("$<$:/utf-8>") + add_compile_options("$<$:/MP>") + add_compile_options("$<$:/MP>") + + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") +endif() + +add_compile_options("$<$:/W4>") +add_compile_options("$<$>:-Wall;-Wextra;-Wpedantic>") +add_library(MeoAssistantDart SHARED src/AsstDartApi.cpp) +set(CMAKE_CXX_STANDARD 17) +set(MAA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../..") + + +include_directories("include" "${MAA_ROOT}/include" "dart" "dart/internal") +find_library(MeoAssistant PATHS "${CMAKE_CURRENT_SOURCE}/lib") + + +target_link_libraries(MeoAssistantDart PUBLIC ${MeoAssitant}) +install(TARGETS MeoAssistantDart DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/../linux") +install(FILES lib/libMeoAssistant.so DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/../linux") diff --git a/src/dart/native/dart/dart_api.h b/src/dart/native/dart/dart_api.h new file mode 100644 index 0000000000..f37de2b819 --- /dev/null +++ b/src/dart/native/dart/dart_api.h @@ -0,0 +1,4016 @@ +/* + * Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_INCLUDE_DART_API_H_ +#define RUNTIME_INCLUDE_DART_API_H_ + +/** \mainpage Dart Embedding API Reference + * + * This reference describes the Dart Embedding API, which is used to embed the + * Dart Virtual Machine within C/C++ applications. + * + * This reference is generated from the header include/dart_api.h. + */ + +/* __STDC_FORMAT_MACROS has to be defined before including to + * enable platform independent printf format specifiers. */ +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif + +#include +#include +#include + +#ifdef __cplusplus +#define DART_EXTERN_C extern "C" +#else +#define DART_EXTERN_C extern +#endif + +#if defined(__CYGWIN__) +#error Tool chain and platform not supported. +#elif defined(_WIN32) +#if defined(DART_SHARED_LIB) +#define DART_EXPORT DART_EXTERN_C __declspec(dllexport) +#else +#define DART_EXPORT DART_EXTERN_C +#endif +#else +#if __GNUC__ >= 4 +#if defined(DART_SHARED_LIB) +#define DART_EXPORT \ + DART_EXTERN_C __attribute__((visibility("default"))) __attribute((used)) +#else +#define DART_EXPORT DART_EXTERN_C +#endif +#else +#error Tool chain not supported. +#endif +#endif + +#if __GNUC__ +#define DART_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#elif _MSC_VER +#define DART_WARN_UNUSED_RESULT _Check_return_ +#else +#define DART_WARN_UNUSED_RESULT +#endif + +/* + * ======= + * Handles + * ======= + */ + +/** + * An isolate is the unit of concurrency in Dart. Each isolate has + * its own memory and thread of control. No state is shared between + * isolates. Instead, isolates communicate by message passing. + * + * Each thread keeps track of its current isolate, which is the + * isolate which is ready to execute on the current thread. The + * current isolate may be NULL, in which case no isolate is ready to + * execute. Most of the Dart apis require there to be a current + * isolate in order to function without error. The current isolate is + * set by any call to Dart_CreateIsolateGroup or Dart_EnterIsolate. + */ +typedef struct _Dart_Isolate* Dart_Isolate; +typedef struct _Dart_IsolateGroup* Dart_IsolateGroup; + +/** + * An object reference managed by the Dart VM garbage collector. + * + * Because the garbage collector may move objects, it is unsafe to + * refer to objects directly. Instead, we refer to objects through + * handles, which are known to the garbage collector and updated + * automatically when the object is moved. Handles should be passed + * by value (except in cases like out-parameters) and should never be + * allocated on the heap. + * + * Most functions in the Dart Embedding API return a handle. When a + * function completes normally, this will be a valid handle to an + * object in the Dart VM heap. This handle may represent the result of + * the operation or it may be a special valid handle used merely to + * indicate successful completion. Note that a valid handle may in + * some cases refer to the null object. + * + * --- Error handles --- + * + * When a function encounters a problem that prevents it from + * completing normally, it returns an error handle (See Dart_IsError). + * An error handle has an associated error message that gives more + * details about the problem (See Dart_GetError). + * + * There are four kinds of error handles that can be produced, + * depending on what goes wrong: + * + * - Api error handles are produced when an api function is misused. + * This happens when a Dart embedding api function is called with + * invalid arguments or in an invalid context. + * + * - Unhandled exception error handles are produced when, during the + * execution of Dart code, an exception is thrown but not caught. + * Prototypically this would occur during a call to Dart_Invoke, but + * it can occur in any function which triggers the execution of Dart + * code (for example, Dart_ToString). + * + * An unhandled exception error provides access to an exception and + * stacktrace via the functions Dart_ErrorGetException and + * Dart_ErrorGetStackTrace. + * + * - Compilation error handles are produced when, during the execution + * of Dart code, a compile-time error occurs. As above, this can + * occur in any function which triggers the execution of Dart code. + * + * - Fatal error handles are produced when the system wants to shut + * down the current isolate. + * + * --- Propagating errors --- + * + * When an error handle is returned from the top level invocation of + * Dart code in a program, the embedder must handle the error as they + * see fit. Often, the embedder will print the error message produced + * by Dart_Error and exit the program. + * + * When an error is returned while in the body of a native function, + * it can be propagated up the call stack by calling + * Dart_PropagateError, Dart_SetReturnValue, or Dart_ThrowException. + * Errors should be propagated unless there is a specific reason not + * to. If an error is not propagated then it is ignored. For + * example, if an unhandled exception error is ignored, that + * effectively "catches" the unhandled exception. Fatal errors must + * always be propagated. + * + * When an error is propagated, any current scopes created by + * Dart_EnterScope will be exited. + * + * Using Dart_SetReturnValue to propagate an exception is somewhat + * more convenient than using Dart_PropagateError, and should be + * preferred for reasons discussed below. + * + * Dart_PropagateError and Dart_ThrowException do not return. Instead + * they transfer control non-locally using a setjmp-like mechanism. + * This can be inconvenient if you have resources that you need to + * clean up before propagating the error. + * + * When relying on Dart_PropagateError, we often return error handles + * rather than propagating them from helper functions. Consider the + * following contrived example: + * + * 1 Dart_Handle isLongStringHelper(Dart_Handle arg) { + * 2 intptr_t* length = 0; + * 3 result = Dart_StringLength(arg, &length); + * 4 if (Dart_IsError(result)) { + * 5 return result; + * 6 } + * 7 return Dart_NewBoolean(length > 100); + * 8 } + * 9 + * 10 void NativeFunction_isLongString(Dart_NativeArguments args) { + * 11 Dart_EnterScope(); + * 12 AllocateMyResource(); + * 13 Dart_Handle arg = Dart_GetNativeArgument(args, 0); + * 14 Dart_Handle result = isLongStringHelper(arg); + * 15 if (Dart_IsError(result)) { + * 16 FreeMyResource(); + * 17 Dart_PropagateError(result); + * 18 abort(); // will not reach here + * 19 } + * 20 Dart_SetReturnValue(result); + * 21 FreeMyResource(); + * 22 Dart_ExitScope(); + * 23 } + * + * In this example, we have a native function which calls a helper + * function to do its work. On line 5, the helper function could call + * Dart_PropagateError, but that would not give the native function a + * chance to call FreeMyResource(), causing a leak. Instead, the + * helper function returns the error handle to the caller, giving the + * caller a chance to clean up before propagating the error handle. + * + * When an error is propagated by calling Dart_SetReturnValue, the + * native function will be allowed to complete normally and then the + * exception will be propagated only once the native call + * returns. This can be convenient, as it allows the C code to clean + * up normally. + * + * The example can be written more simply using Dart_SetReturnValue to + * propagate the error. + * + * 1 Dart_Handle isLongStringHelper(Dart_Handle arg) { + * 2 intptr_t* length = 0; + * 3 result = Dart_StringLength(arg, &length); + * 4 if (Dart_IsError(result)) { + * 5 return result + * 6 } + * 7 return Dart_NewBoolean(length > 100); + * 8 } + * 9 + * 10 void NativeFunction_isLongString(Dart_NativeArguments args) { + * 11 Dart_EnterScope(); + * 12 AllocateMyResource(); + * 13 Dart_Handle arg = Dart_GetNativeArgument(args, 0); + * 14 Dart_SetReturnValue(isLongStringHelper(arg)); + * 15 FreeMyResource(); + * 16 Dart_ExitScope(); + * 17 } + * + * In this example, the call to Dart_SetReturnValue on line 14 will + * either return the normal return value or the error (potentially + * generated on line 3). The call to FreeMyResource on line 15 will + * execute in either case. + * + * --- Local and persistent handles --- + * + * Local handles are allocated within the current scope (see + * Dart_EnterScope) and go away when the current scope exits. Unless + * otherwise indicated, callers should assume that all functions in + * the Dart embedding api return local handles. + * + * Persistent handles are allocated within the current isolate. They + * can be used to store objects across scopes. Persistent handles have + * the lifetime of the current isolate unless they are explicitly + * deallocated (see Dart_DeletePersistentHandle). + * The type Dart_Handle represents a handle (both local and persistent). + * The type Dart_PersistentHandle is a Dart_Handle and it is used to + * document that a persistent handle is expected as a parameter to a call + * or the return value from a call is a persistent handle. + * + * FinalizableHandles are persistent handles which are auto deleted when + * the object is garbage collected. It is never safe to use these handles + * unless you know the object is still reachable. + * + * WeakPersistentHandles are persistent handles which are automatically set + * to point Dart_Null when the object is garbage collected. They are not auto + * deleted, so it is safe to use them after the object has become unreachable. + */ +typedef struct _Dart_Handle* Dart_Handle; +typedef Dart_Handle Dart_PersistentHandle; +typedef struct _Dart_WeakPersistentHandle* Dart_WeakPersistentHandle; +typedef struct _Dart_FinalizableHandle* Dart_FinalizableHandle; +// These structs are versioned by DART_API_DL_MAJOR_VERSION, bump the +// version when changing this struct. + +typedef void (*Dart_HandleFinalizer)(void* isolate_callback_data, void* peer); + +/** + * Is this an error handle? + * + * Requires there to be a current isolate. + */ +DART_EXPORT bool Dart_IsError(Dart_Handle handle); + +/** + * Is this an api error handle? + * + * Api error handles are produced when an api function is misused. + * This happens when a Dart embedding api function is called with + * invalid arguments or in an invalid context. + * + * Requires there to be a current isolate. + */ +DART_EXPORT bool Dart_IsApiError(Dart_Handle handle); + +/** + * Is this an unhandled exception error handle? + * + * Unhandled exception error handles are produced when, during the + * execution of Dart code, an exception is thrown but not caught. + * This can occur in any function which triggers the execution of Dart + * code. + * + * See Dart_ErrorGetException and Dart_ErrorGetStackTrace. + * + * Requires there to be a current isolate. + */ +DART_EXPORT bool Dart_IsUnhandledExceptionError(Dart_Handle handle); + +/** + * Is this a compilation error handle? + * + * Compilation error handles are produced when, during the execution + * of Dart code, a compile-time error occurs. This can occur in any + * function which triggers the execution of Dart code. + * + * Requires there to be a current isolate. + */ +DART_EXPORT bool Dart_IsCompilationError(Dart_Handle handle); + +/** + * Is this a fatal error handle? + * + * Fatal error handles are produced when the system wants to shut down + * the current isolate. + * + * Requires there to be a current isolate. + */ +DART_EXPORT bool Dart_IsFatalError(Dart_Handle handle); + +/** + * Gets the error message from an error handle. + * + * Requires there to be a current isolate. + * + * \return A C string containing an error message if the handle is + * error. An empty C string ("") if the handle is valid. This C + * String is scope allocated and is only valid until the next call + * to Dart_ExitScope. +*/ +DART_EXPORT const char* Dart_GetError(Dart_Handle handle); + +/** + * Is this an error handle for an unhandled exception? + */ +DART_EXPORT bool Dart_ErrorHasException(Dart_Handle handle); + +/** + * Gets the exception Object from an unhandled exception error handle. + */ +DART_EXPORT Dart_Handle Dart_ErrorGetException(Dart_Handle handle); + +/** + * Gets the stack trace Object from an unhandled exception error handle. + */ +DART_EXPORT Dart_Handle Dart_ErrorGetStackTrace(Dart_Handle handle); + +/** + * Produces an api error handle with the provided error message. + * + * Requires there to be a current isolate. + * + * \param error the error message. + */ +DART_EXPORT Dart_Handle Dart_NewApiError(const char* error); +DART_EXPORT Dart_Handle Dart_NewCompilationError(const char* error); + +/** + * Produces a new unhandled exception error handle. + * + * Requires there to be a current isolate. + * + * \param exception An instance of a Dart object to be thrown or + * an ApiError or CompilationError handle. + * When an ApiError or CompilationError handle is passed in + * a string object of the error message is created and it becomes + * the Dart object to be thrown. + */ +DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception); + +/** + * Propagates an error. + * + * If the provided handle is an unhandled exception error, this + * function will cause the unhandled exception to be rethrown. This + * will proceed in the standard way, walking up Dart frames until an + * appropriate 'catch' block is found, executing 'finally' blocks, + * etc. + * + * If the error is not an unhandled exception error, we will unwind + * the stack to the next C frame. Intervening Dart frames will be + * discarded; specifically, 'finally' blocks will not execute. This + * is the standard way that compilation errors (and the like) are + * handled by the Dart runtime. + * + * In either case, when an error is propagated any current scopes + * created by Dart_EnterScope will be exited. + * + * See the additional discussion under "Propagating Errors" at the + * beginning of this file. + * + * \param handle An error handle (See Dart_IsError) + * + * On success, this function does not return. On failure, the + * process is terminated. + */ +DART_EXPORT void Dart_PropagateError(Dart_Handle handle); + +/** + * Converts an object to a string. + * + * May generate an unhandled exception error. + * + * \return The converted string if no error occurs during + * the conversion. If an error does occur, an error handle is + * returned. + */ +DART_EXPORT Dart_Handle Dart_ToString(Dart_Handle object); + +/** + * Checks to see if two handles refer to identically equal objects. + * + * If both handles refer to instances, this is equivalent to using the top-level + * function identical() from dart:core. Otherwise, returns whether the two + * argument handles refer to the same object. + * + * \param obj1 An object to be compared. + * \param obj2 An object to be compared. + * + * \return True if the objects are identically equal. False otherwise. + */ +DART_EXPORT bool Dart_IdentityEquals(Dart_Handle obj1, Dart_Handle obj2); + +/** + * Allocates a handle in the current scope from a persistent handle. + */ +DART_EXPORT Dart_Handle Dart_HandleFromPersistent(Dart_PersistentHandle object); + +/** + * Allocates a handle in the current scope from a weak persistent handle. + * + * This will be a handle to Dart_Null if the object has been garbage collected. + */ +DART_EXPORT Dart_Handle +Dart_HandleFromWeakPersistent(Dart_WeakPersistentHandle object); + +/** + * Allocates a persistent handle for an object. + * + * This handle has the lifetime of the current isolate unless it is + * explicitly deallocated by calling Dart_DeletePersistentHandle. + * + * Requires there to be a current isolate. + */ +DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object); + +/** + * Assign value of local handle to a persistent handle. + * + * Requires there to be a current isolate. + * + * \param obj1 A persistent handle whose value needs to be set. + * \param obj2 An object whose value needs to be set to the persistent handle. + */ +DART_EXPORT void Dart_SetPersistentHandle(Dart_PersistentHandle obj1, + Dart_Handle obj2); + +/** + * Deallocates a persistent handle. + * + * Requires there to be a current isolate group. + */ +DART_EXPORT void Dart_DeletePersistentHandle(Dart_PersistentHandle object); + +/** + * Allocates a weak persistent handle for an object. + * + * This handle has the lifetime of the current isolate. The handle can also be + * explicitly deallocated by calling Dart_DeleteWeakPersistentHandle. + * + * If the object becomes unreachable the callback is invoked with the peer as + * argument. The callback can be executed on any thread, will have a current + * isolate group, but will not have a current isolate. The callback can only + * call Dart_DeletePersistentHandle or Dart_DeleteWeakPersistentHandle. This + * gives the embedder the ability to cleanup data associated with the object. + * The handle will point to the Dart_Null object after the finalizer has been + * run. It is illegal to call into the VM with any other Dart_* functions from + * the callback. If the handle is deleted before the object becomes + * unreachable, the callback is never invoked. + * + * Requires there to be a current isolate. + * + * \param object An object with identity. + * \param peer A pointer to a native object or NULL. This value is + * provided to callback when it is invoked. + * \param external_allocation_size The number of externally allocated + * bytes for peer. Used to inform the garbage collector. + * \param callback A function pointer that will be invoked sometime + * after the object is garbage collected, unless the handle has been deleted. + * A valid callback needs to be specified it cannot be NULL. + * + * \return The weak persistent handle or NULL. NULL is returned in case of bad + * parameters. + */ +DART_EXPORT Dart_WeakPersistentHandle +Dart_NewWeakPersistentHandle(Dart_Handle object, + void* peer, + intptr_t external_allocation_size, + Dart_HandleFinalizer callback); + +/** + * Deletes the given weak persistent [object] handle. + * + * Requires there to be a current isolate group. + */ +DART_EXPORT void Dart_DeleteWeakPersistentHandle( + Dart_WeakPersistentHandle object); + +/** + * Updates the external memory size for the given weak persistent handle. + * + * May trigger garbage collection. + */ +DART_EXPORT void Dart_UpdateExternalSize(Dart_WeakPersistentHandle object, + intptr_t external_allocation_size); + +/** + * Allocates a finalizable handle for an object. + * + * This handle has the lifetime of the current isolate group unless the object + * pointed to by the handle is garbage collected, in this case the VM + * automatically deletes the handle after invoking the callback associated + * with the handle. The handle can also be explicitly deallocated by + * calling Dart_DeleteFinalizableHandle. + * + * If the object becomes unreachable the callback is invoked with the + * the peer as argument. The callback can be executed on any thread, will have + * an isolate group, but will not have a current isolate. The callback can only + * call Dart_DeletePersistentHandle or Dart_DeleteWeakPersistentHandle. + * This gives the embedder the ability to cleanup data associated with the + * object and clear out any cached references to the handle. All references to + * this handle after the callback will be invalid. It is illegal to call into + * the VM with any other Dart_* functions from the callback. If the handle is + * deleted before the object becomes unreachable, the callback is never + * invoked. + * + * Requires there to be a current isolate. + * + * \param object An object with identity. + * \param peer A pointer to a native object or NULL. This value is + * provided to callback when it is invoked. + * \param external_allocation_size The number of externally allocated + * bytes for peer. Used to inform the garbage collector. + * \param callback A function pointer that will be invoked sometime + * after the object is garbage collected, unless the handle has been deleted. + * A valid callback needs to be specified it cannot be NULL. + * + * \return The finalizable handle or NULL. NULL is returned in case of bad + * parameters. + */ +DART_EXPORT Dart_FinalizableHandle +Dart_NewFinalizableHandle(Dart_Handle object, + void* peer, + intptr_t external_allocation_size, + Dart_HandleFinalizer callback); + +/** + * Deletes the given finalizable [object] handle. + * + * The caller has to provide the actual Dart object the handle was created from + * to prove the object (and therefore the finalizable handle) is still alive. + * + * Requires there to be a current isolate. + */ +DART_EXPORT void Dart_DeleteFinalizableHandle(Dart_FinalizableHandle object, + Dart_Handle strong_ref_to_object); + +/** + * Updates the external memory size for the given finalizable handle. + * + * The caller has to provide the actual Dart object the handle was created from + * to prove the object (and therefore the finalizable handle) is still alive. + * + * May trigger garbage collection. + */ +DART_EXPORT void Dart_UpdateFinalizableExternalSize( + Dart_FinalizableHandle object, + Dart_Handle strong_ref_to_object, + intptr_t external_allocation_size); + +/* + * ========================== + * Initialization and Globals + * ========================== + */ + +/** + * Gets the version string for the Dart VM. + * + * The version of the Dart VM can be accessed without initializing the VM. + * + * \return The version string for the embedded Dart VM. + */ +DART_EXPORT const char* Dart_VersionString(void); + +/** + * Isolate specific flags are set when creating a new isolate using the + * Dart_IsolateFlags structure. + * + * Current version of flags is encoded in a 32-bit integer with 16 bits used + * for each part. + */ + +#define DART_FLAGS_CURRENT_VERSION (0x0000000c) + +typedef struct { + int32_t version; + bool enable_asserts; + bool use_field_guards; + bool use_osr; + bool obfuscate; + bool load_vmservice_library; + bool copy_parent_code; + bool null_safety; + bool is_system_isolate; + bool snapshot_is_dontneed_safe; + bool branch_coverage; +} Dart_IsolateFlags; + +/** + * Initialize Dart_IsolateFlags with correct version and default values. + */ +DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags); + +/** + * An isolate creation and initialization callback function. + * + * This callback, provided by the embedder, is called when the VM + * needs to create an isolate. The callback should create an isolate + * by calling Dart_CreateIsolateGroup and load any scripts required for + * execution. + * + * This callback may be called on a different thread than the one + * running the parent isolate. + * + * When the function returns NULL, it is the responsibility of this + * function to ensure that Dart_ShutdownIsolate has been called if + * required (for example, if the isolate was created successfully by + * Dart_CreateIsolateGroup() but the root library fails to load + * successfully, then the function should call Dart_ShutdownIsolate + * before returning). + * + * When the function returns NULL, the function should set *error to + * a malloc-allocated buffer containing a useful error message. The + * caller of this function (the VM) will make sure that the buffer is + * freed. + * + * \param script_uri The uri of the main source file or snapshot to load. + * Either the URI of the parent isolate set in Dart_CreateIsolateGroup for + * Isolate.spawn, or the argument to Isolate.spawnUri canonicalized by the + * library tag handler of the parent isolate. + * The callback is responsible for loading the program by a call to + * Dart_LoadScriptFromKernel. + * \param main The name of the main entry point this isolate will + * eventually run. This is provided for advisory purposes only to + * improve debugging messages. The main function is not invoked by + * this function. + * \param package_root Ignored. + * \param package_config Uri of the package configuration file (either in format + * of .packages or .dart_tool/package_config.json) for this isolate + * to resolve package imports against. If this parameter is not passed the + * package resolution of the parent isolate should be used. + * \param flags Default flags for this isolate being spawned. Either inherited + * from the spawning isolate or passed as parameters when spawning the + * isolate from Dart code. + * \param isolate_data The isolate data which was passed to the + * parent isolate when it was created by calling Dart_CreateIsolateGroup(). + * \param error A structure into which the embedder can place a + * C string containing an error message in the case of failures. + * + * \return The embedder returns NULL if the creation and + * initialization was not successful and the isolate if successful. + */ +typedef Dart_Isolate (*Dart_IsolateGroupCreateCallback)( + const char* script_uri, + const char* main, + const char* package_root, + const char* package_config, + Dart_IsolateFlags* flags, + void* isolate_data, + char** error); + +/** + * An isolate initialization callback function. + * + * This callback, provided by the embedder, is called when the VM has created an + * isolate within an existing isolate group (i.e. from the same source as an + * existing isolate). + * + * The callback should setup native resolvers and might want to set a custom + * message handler via [Dart_SetMessageNotifyCallback] and mark the isolate as + * runnable. + * + * This callback may be called on a different thread than the one + * running the parent isolate. + * + * When the function returns `false`, it is the responsibility of this + * function to ensure that `Dart_ShutdownIsolate` has been called. + * + * When the function returns `false`, the function should set *error to + * a malloc-allocated buffer containing a useful error message. The + * caller of this function (the VM) will make sure that the buffer is + * freed. + * + * \param child_isolate_data The callback data to associate with the new + * child isolate. + * \param error A structure into which the embedder can place a + * C string containing an error message in the case the initialization fails. + * + * \return The embedder returns true if the initialization was successful and + * false otherwise (in which case the VM will terminate the isolate). + */ +typedef bool (*Dart_InitializeIsolateCallback)(void** child_isolate_data, + char** error); + +/** + * An isolate unhandled exception callback function. + * + * This callback has been DEPRECATED. + */ +typedef void (*Dart_IsolateUnhandledExceptionCallback)(Dart_Handle error); + +/** + * An isolate shutdown callback function. + * + * This callback, provided by the embedder, is called before the vm + * shuts down an isolate. The isolate being shutdown will be the current + * isolate. It is safe to run Dart code. + * + * This function should be used to dispose of native resources that + * are allocated to an isolate in order to avoid leaks. + * + * \param isolate_group_data The same callback data which was passed to the + * isolate group when it was created. + * \param isolate_data The same callback data which was passed to the isolate + * when it was created. + */ +typedef void (*Dart_IsolateShutdownCallback)(void* isolate_group_data, + void* isolate_data); + +/** + * An isolate cleanup callback function. + * + * This callback, provided by the embedder, is called after the vm + * shuts down an isolate. There will be no current isolate and it is *not* + * safe to run Dart code. + * + * This function should be used to dispose of native resources that + * are allocated to an isolate in order to avoid leaks. + * + * \param isolate_group_data The same callback data which was passed to the + * isolate group when it was created. + * \param isolate_data The same callback data which was passed to the isolate + * when it was created. + */ +typedef void (*Dart_IsolateCleanupCallback)(void* isolate_group_data, + void* isolate_data); + +/** + * An isolate group cleanup callback function. + * + * This callback, provided by the embedder, is called after the vm + * shuts down an isolate group. + * + * This function should be used to dispose of native resources that + * are allocated to an isolate in order to avoid leaks. + * + * \param isolate_group_data The same callback data which was passed to the + * isolate group when it was created. + * + */ +typedef void (*Dart_IsolateGroupCleanupCallback)(void* isolate_group_data); + +/** + * A thread death callback function. + * This callback, provided by the embedder, is called before a thread in the + * vm thread pool exits. + * This function could be used to dispose of native resources that + * are associated and attached to the thread, in order to avoid leaks. + */ +typedef void (*Dart_ThreadExitCallback)(void); + +/** + * Opens a file for reading or writing. + * + * Callback provided by the embedder for file operations. If the + * embedder does not allow file operations this callback can be + * NULL. + * + * \param name The name of the file to open. + * \param write A boolean variable which indicates if the file is to + * opened for writing. If there is an existing file it needs to truncated. + */ +typedef void* (*Dart_FileOpenCallback)(const char* name, bool write); + +/** + * Read contents of file. + * + * Callback provided by the embedder for file operations. If the + * embedder does not allow file operations this callback can be + * NULL. + * + * \param data Buffer allocated in the callback into which the contents + * of the file are read into. It is the responsibility of the caller to + * free this buffer. + * \param file_length A variable into which the length of the file is returned. + * In the case of an error this value would be -1. + * \param stream Handle to the opened file. + */ +typedef void (*Dart_FileReadCallback)(uint8_t** data, + intptr_t* file_length, + void* stream); + +/** + * Write data into file. + * + * Callback provided by the embedder for file operations. If the + * embedder does not allow file operations this callback can be + * NULL. + * + * \param data Buffer which needs to be written into the file. + * \param length Length of the buffer. + * \param stream Handle to the opened file. + */ +typedef void (*Dart_FileWriteCallback)(const void* data, + intptr_t length, + void* stream); + +/** + * Closes the opened file. + * + * Callback provided by the embedder for file operations. If the + * embedder does not allow file operations this callback can be + * NULL. + * + * \param stream Handle to the opened file. + */ +typedef void (*Dart_FileCloseCallback)(void* stream); + +typedef bool (*Dart_EntropySource)(uint8_t* buffer, intptr_t length); + +/** + * Callback provided by the embedder that is used by the vmservice isolate + * to request the asset archive. The asset archive must be an uncompressed tar + * archive that is stored in a Uint8List. + * + * If the embedder has no vmservice isolate assets, the callback can be NULL. + * + * \return The embedder must return a handle to a Uint8List containing an + * uncompressed tar archive or null. + */ +typedef Dart_Handle (*Dart_GetVMServiceAssetsArchive)(void); + +/** + * The current version of the Dart_InitializeFlags. Should be incremented every + * time Dart_InitializeFlags changes in a binary incompatible way. + */ +#define DART_INITIALIZE_PARAMS_CURRENT_VERSION (0x00000005) + +/** Forward declaration */ +struct Dart_CodeObserver; + +/** + * Callback provided by the embedder that is used by the VM to notify on code + * object creation, *before* it is invoked the first time. + * This is useful for embedders wanting to e.g. keep track of PCs beyond + * the lifetime of the garbage collected code objects. + * Note that an address range may be used by more than one code object over the + * lifecycle of a process. Clients of this function should record timestamps for + * these compilation events and when collecting PCs to disambiguate reused + * address ranges. + */ +typedef void (*Dart_OnNewCodeCallback)(struct Dart_CodeObserver* observer, + const char* name, + uintptr_t base, + uintptr_t size); + +typedef struct Dart_CodeObserver { + void* data; + + Dart_OnNewCodeCallback on_new_code; +} Dart_CodeObserver; + +typedef struct _Dart_Task* Dart_Task; +typedef enum { + Dart_TaskPriority_Default, +} Dart_TaskPriority; +typedef struct { + /** + * Placeholder. + */ + Dart_TaskPriority priority; + /** + * Time after which the task should run according to the clock of + * Dart_TimelineGetMicros. + */ + int64_t time_point; +} Dart_TaskData; +/** + * Callback provided by the embedder that is used by the VM to eventually run + * various tasks. If no callback is provided, these tasks will run on a + * VM-internal thread pool. This callback allows the embedder to make its own + * choices around the scheduling of these tasks: when they run, how many threads + * are servicing these tasks, the priorities of said threads, etc. + * The callback can be invoked as early as during the Dart_Initialize call. + * + * \param post_task_data + * The data provided to Dart_InitializeParams.post_task_data. + * \param task + * A task that should eventually be passed to Dart_RunTask. + * \param task_data + * Hints about when the task should run. + */ +typedef void (*Dart_PostTaskCallback)(void* post_task_data, + Dart_Task task, + Dart_TaskData task_data); + +/** + * Runs a task given to the Dart_PostTaskCallback. Must not be called + * synchronously in response to any callback from the VM. In particular, must + * not be called synchronously by the implemention of a Dart native function + * or Dart_Post_TaskCallback. + * + * Requires there to be no current isolate or isolate group. + */ +DART_EXPORT void Dart_RunTask(Dart_Task task); + +/** + * Describes how to initialize the VM. Used with Dart_Initialize. + */ +typedef struct { + /** + * Identifies the version of the struct used by the client. + * should be initialized to DART_INITIALIZE_PARAMS_CURRENT_VERSION. + */ + int32_t version; + + /** + * A buffer containing snapshot data, or NULL if no snapshot is provided. + * + * If provided, the buffer must remain valid until Dart_Cleanup returns. + */ + const uint8_t* vm_snapshot_data; + + /** + * A buffer containing a snapshot of precompiled instructions, or NULL if + * no snapshot is provided. + * + * If provided, the buffer must remain valid until Dart_Cleanup returns. + */ + const uint8_t* vm_snapshot_instructions; + + /** + * A function to be called during isolate group creation. + * See Dart_IsolateGroupCreateCallback. + */ + Dart_IsolateGroupCreateCallback create_group; + + /** + * A function to be called during isolate + * initialization inside an existing isolate group. + * See Dart_InitializeIsolateCallback. + */ + Dart_InitializeIsolateCallback initialize_isolate; + + /** + * A function to be called right before an isolate is shutdown. + * See Dart_IsolateShutdownCallback. + */ + Dart_IsolateShutdownCallback shutdown_isolate; + + /** + * A function to be called after an isolate was shutdown. + * See Dart_IsolateCleanupCallback. + */ + Dart_IsolateCleanupCallback cleanup_isolate; + + /** + * A function to be called after an isolate group is + * shutdown. See Dart_IsolateGroupCleanupCallback. + */ + Dart_IsolateGroupCleanupCallback cleanup_group; + + Dart_ThreadExitCallback thread_exit; + Dart_FileOpenCallback file_open; + Dart_FileReadCallback file_read; + Dart_FileWriteCallback file_write; + Dart_FileCloseCallback file_close; + Dart_EntropySource entropy_source; + + /** + * A function to be called by the service isolate when it requires the + * vmservice assets archive. See Dart_GetVMServiceAssetsArchive. + */ + Dart_GetVMServiceAssetsArchive get_service_assets; + + bool start_kernel_isolate; + + /** + * An external code observer callback function. The observer can be invoked + * as early as during the Dart_Initialize() call. + */ + Dart_CodeObserver* code_observer; + + /** + * A task scheduling callback function. See Dart_PostTaskCallback. + */ + Dart_PostTaskCallback post_task; + + void* post_task_data; +} Dart_InitializeParams; + +/** + * Initializes the VM. + * + * \param params A struct containing initialization information. The version + * field of the struct must be DART_INITIALIZE_PARAMS_CURRENT_VERSION. + * + * \return NULL if initialization is successful. Returns an error message + * otherwise. The caller is responsible for freeing the error message. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_Initialize( + Dart_InitializeParams* params); + +/** + * Cleanup state in the VM before process termination. + * + * \return NULL if cleanup is successful. Returns an error message otherwise. + * The caller is responsible for freeing the error message. + * + * NOTE: This function must not be called on a thread that was created by the VM + * itself. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_Cleanup(void); + +/** + * Sets command line flags. Should be called before Dart_Initialize. + * + * \param argc The length of the arguments array. + * \param argv An array of arguments. + * + * \return NULL if successful. Returns an error message otherwise. + * The caller is responsible for freeing the error message. + * + * NOTE: This call does not store references to the passed in c-strings. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_SetVMFlags(int argc, + const char** argv); + +/** + * Returns true if the named VM flag is of boolean type, specified, and set to + * true. + * + * \param flag_name The name of the flag without leading punctuation + * (example: "enable_asserts"). + */ +DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name); + +/* + * ======== + * Isolates + * ======== + */ + +/** + * Creates a new isolate. The new isolate becomes the current isolate. + * + * A snapshot can be used to restore the VM quickly to a saved state + * and is useful for fast startup. If snapshot data is provided, the + * isolate will be started using that snapshot data. Requires a core snapshot or + * an app snapshot created by Dart_CreateSnapshot or + * Dart_CreatePrecompiledSnapshot* from a VM with the same version. + * + * Requires there to be no current isolate. + * + * \param script_uri The main source file or snapshot this isolate will load. + * The VM will provide this URI to the Dart_IsolateGroupCreateCallback when a + * child isolate is created by Isolate.spawn. The embedder should use a URI + * that allows it to load the same program into such a child isolate. + * \param name A short name for the isolate to improve debugging messages. + * Typically of the format 'foo.dart:main()'. + * \param isolate_snapshot_data Buffer containing the snapshot data of the + * isolate or NULL if no snapshot is provided. If provided, the buffer must + * remain valid until the isolate shuts down. + * \param isolate_snapshot_instructions Buffer containing the snapshot + * instructions of the isolate or NULL if no snapshot is provided. If + * provided, the buffer must remain valid until the isolate shuts down. + * \param flags Pointer to VM specific flags or NULL for default flags. + * \param isolate_group_data Embedder group data. This data can be obtained + * by calling Dart_IsolateGroupData and will be passed to the + * Dart_IsolateShutdownCallback, Dart_IsolateCleanupCallback, and + * Dart_IsolateGroupCleanupCallback. + * \param isolate_data Embedder data. This data will be passed to + * the Dart_IsolateGroupCreateCallback when new isolates are spawned from + * this parent isolate. + * \param error Returns NULL if creation is successful, an error message + * otherwise. The caller is responsible for calling free() on the error + * message. + * + * \return The new isolate on success, or NULL if isolate creation failed. + */ +DART_EXPORT Dart_Isolate +Dart_CreateIsolateGroup(const char* script_uri, + const char* name, + const uint8_t* isolate_snapshot_data, + const uint8_t* isolate_snapshot_instructions, + Dart_IsolateFlags* flags, + void* isolate_group_data, + void* isolate_data, + char** error); +/** + * Creates a new isolate inside the isolate group of [group_member]. + * + * Requires there to be no current isolate. + * + * \param group_member An isolate from the same group into which the newly created + * isolate should be born into. Other threads may not have entered / enter this + * member isolate. + * \param name A short name for the isolate for debugging purposes. + * \param shutdown_callback A callback to be called when the isolate is being + * shutdown (may be NULL). + * \param cleanup_callback A callback to be called when the isolate is being + * cleaned up (may be NULL). + * \param isolate_data The embedder-specific data associated with this isolate. + * \param error Set to NULL if creation is successful, set to an error + * message otherwise. The caller is responsible for calling free() on the + * error message. + * + * \return The newly created isolate on success, or NULL if isolate creation + * failed. + * + * If successful, the newly created isolate will become the current isolate. + */ +DART_EXPORT Dart_Isolate +Dart_CreateIsolateInGroup(Dart_Isolate group_member, + const char* name, + Dart_IsolateShutdownCallback shutdown_callback, + Dart_IsolateCleanupCallback cleanup_callback, + void* child_isolate_data, + char** error); + +/* TODO(turnidge): Document behavior when there is already a current + * isolate. */ + +/** + * Creates a new isolate from a Dart Kernel file. The new isolate + * becomes the current isolate. + * + * Requires there to be no current isolate. + * + * \param script_uri The main source file or snapshot this isolate will load. + * The VM will provide this URI to the Dart_IsolateGroupCreateCallback when a + * child isolate is created by Isolate.spawn. The embedder should use a URI that + * allows it to load the same program into such a child isolate. + * \param name A short name for the isolate to improve debugging messages. + * Typically of the format 'foo.dart:main()'. + * \param kernel_buffer A buffer which contains a kernel/DIL program. Must + * remain valid until isolate shutdown. + * \param kernel_buffer_size The size of `kernel_buffer`. + * \param flags Pointer to VM specific flags or NULL for default flags. + * \param isolate_group_data Embedder group data. This data can be obtained + * by calling Dart_IsolateGroupData and will be passed to the + * Dart_IsolateShutdownCallback, Dart_IsolateCleanupCallback, and + * Dart_IsolateGroupCleanupCallback. + * \param isolate_data Embedder data. This data will be passed to + * the Dart_IsolateGroupCreateCallback when new isolates are spawned from + * this parent isolate. + * \param error Returns NULL if creation is successful, an error message + * otherwise. The caller is responsible for calling free() on the error + * message. + * + * \return The new isolate on success, or NULL if isolate creation failed. + */ +DART_EXPORT Dart_Isolate +Dart_CreateIsolateGroupFromKernel(const char* script_uri, + const char* name, + const uint8_t* kernel_buffer, + intptr_t kernel_buffer_size, + Dart_IsolateFlags* flags, + void* isolate_group_data, + void* isolate_data, + char** error); +/** + * Shuts down the current isolate. After this call, the current isolate is NULL. + * Any current scopes created by Dart_EnterScope will be exited. Invokes the + * shutdown callback and any callbacks of remaining weak persistent handles. + * + * Requires there to be a current isolate. + */ +DART_EXPORT void Dart_ShutdownIsolate(void); +/* TODO(turnidge): Document behavior when there is no current isolate. */ + +/** + * Returns the current isolate. Will return NULL if there is no + * current isolate. + */ +DART_EXPORT Dart_Isolate Dart_CurrentIsolate(void); + +/** + * Returns the callback data associated with the current isolate. This + * data was set when the isolate got created or initialized. + */ +DART_EXPORT void* Dart_CurrentIsolateData(void); + +/** + * Returns the callback data associated with the given isolate. This + * data was set when the isolate got created or initialized. + */ +DART_EXPORT void* Dart_IsolateData(Dart_Isolate isolate); + +/** + * Returns the current isolate group. Will return NULL if there is no + * current isolate group. + */ +DART_EXPORT Dart_IsolateGroup Dart_CurrentIsolateGroup(void); + +/** + * Returns the callback data associated with the current isolate group. This + * data was passed to the isolate group when it was created. + */ +DART_EXPORT void* Dart_CurrentIsolateGroupData(void); + +/** + * Returns the callback data associated with the specified isolate group. This + * data was passed to the isolate when it was created. + * The embedder is responsible for ensuring the consistency of this data + * with respect to the lifecycle of an isolate group. + */ +DART_EXPORT void* Dart_IsolateGroupData(Dart_Isolate isolate); + +/** + * Returns the debugging name for the current isolate. + * + * This name is unique to each isolate and should only be used to make + * debugging messages more comprehensible. + */ +DART_EXPORT Dart_Handle Dart_DebugName(void); + +/** + * Returns the ID for an isolate which is used to query the service protocol. + * + * It is the responsibility of the caller to free the returned ID. + */ +DART_EXPORT const char* Dart_IsolateServiceId(Dart_Isolate isolate); + +/** + * Enters an isolate. After calling this function, + * the current isolate will be set to the provided isolate. + * + * Requires there to be no current isolate. Multiple threads may not be in + * the same isolate at once. + */ +DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate); + +/** + * Kills the given isolate. + * + * This function has the same effect as dart:isolate's + * Isolate.kill(priority:immediate). + * It can interrupt ordinary Dart code but not native code. If the isolate is + * in the middle of a long running native function, the isolate will not be + * killed until control returns to Dart. + * + * Does not require a current isolate. It is safe to kill the current isolate if + * there is one. + */ +DART_EXPORT void Dart_KillIsolate(Dart_Isolate isolate); + +/** + * Notifies the VM that the embedder expects |size| bytes of memory have become + * unreachable. The VM may use this hint to adjust the garbage collector's + * growth policy. + * + * Multiple calls are interpreted as increasing, not replacing, the estimate of + * unreachable memory. + * + * Requires there to be a current isolate. + */ +DART_EXPORT void Dart_HintFreed(intptr_t size); + +/** + * Notifies the VM that the embedder expects to be idle until |deadline|. The VM + * may use this time to perform garbage collection or other tasks to avoid + * delays during execution of Dart code in the future. + * + * |deadline| is measured in microseconds against the system's monotonic time. + * This clock can be accessed via Dart_TimelineGetMicros(). + * + * Requires there to be a current isolate. + */ +DART_EXPORT void Dart_NotifyIdle(int64_t deadline); + +/** + * Notifies the VM that the system is running low on memory. + * + * Does not require a current isolate. Only valid after calling Dart_Initialize. + */ +DART_EXPORT void Dart_NotifyLowMemory(void); + +/** + * Starts the CPU sampling profiler. + */ +DART_EXPORT void Dart_StartProfiling(void); + +/** + * Stops the CPU sampling profiler. + * + * Note that some profile samples might still be taken after this fucntion + * returns due to the asynchronous nature of the implementation on some + * platforms. + */ +DART_EXPORT void Dart_StopProfiling(void); + +/** + * Notifies the VM that the current thread should not be profiled until a + * matching call to Dart_ThreadEnableProfiling is made. + * + * NOTE: By default, if a thread has entered an isolate it will be profiled. + * This function should be used when an embedder knows a thread is about + * to make a blocking call and wants to avoid unnecessary interrupts by + * the profiler. + */ +DART_EXPORT void Dart_ThreadDisableProfiling(void); + +/** + * Notifies the VM that the current thread should be profiled. + * + * NOTE: It is only legal to call this function *after* calling + * Dart_ThreadDisableProfiling. + * + * NOTE: By default, if a thread has entered an isolate it will be profiled. + */ +DART_EXPORT void Dart_ThreadEnableProfiling(void); + +/** + * Register symbol information for the Dart VM's profiler and crash dumps. + * + * This consumes the output of //topaz/runtime/dart/profiler_symbols, which + * should be treated as opaque. + */ +DART_EXPORT void Dart_AddSymbols(const char* dso_name, + void* buffer, + intptr_t buffer_size); + +/** + * Exits an isolate. After this call, Dart_CurrentIsolate will + * return NULL. + * + * Requires there to be a current isolate. + */ +DART_EXPORT void Dart_ExitIsolate(void); +/* TODO(turnidge): We don't want users of the api to be able to exit a + * "pure" dart isolate. Implement and document. */ + +/** + * Creates a full snapshot of the current isolate heap. + * + * A full snapshot is a compact representation of the dart vm isolate heap + * and dart isolate heap states. These snapshots are used to initialize + * the vm isolate on startup and fast initialization of an isolate. + * A Snapshot of the heap is created before any dart code has executed. + * + * Requires there to be a current isolate. Not available in the precompiled + * runtime (check Dart_IsPrecompiledRuntime). + * + * \param vm_snapshot_data_buffer Returns a pointer to a buffer containing the + * vm snapshot. This buffer is scope allocated and is only valid + * until the next call to Dart_ExitScope. + * \param vm_snapshot_data_size Returns the size of vm_snapshot_data_buffer. + * \param isolate_snapshot_data_buffer Returns a pointer to a buffer containing + * the isolate snapshot. This buffer is scope allocated and is only valid + * until the next call to Dart_ExitScope. + * \param isolate_snapshot_data_size Returns the size of + * isolate_snapshot_data_buffer. + * \param is_core Create a snapshot containing core libraries. + * Such snapshot should be agnostic to null safety mode. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateSnapshot(uint8_t** vm_snapshot_data_buffer, + intptr_t* vm_snapshot_data_size, + uint8_t** isolate_snapshot_data_buffer, + intptr_t* isolate_snapshot_data_size, + bool is_core); + +/** + * Returns whether the buffer contains a kernel file. + * + * \param buffer Pointer to a buffer that might contain a kernel binary. + * \param buffer_size Size of the buffer. + * + * \return Whether the buffer contains a kernel binary (full or partial). + */ +DART_EXPORT bool Dart_IsKernel(const uint8_t* buffer, intptr_t buffer_size); + +/** + * Make isolate runnable. + * + * When isolates are spawned, this function is used to indicate that + * the creation and initialization (including script loading) of the + * isolate is complete and the isolate can start. + * This function expects there to be no current isolate. + * + * \param isolate The isolate to be made runnable. + * + * \return NULL if successful. Returns an error message otherwise. The caller + * is responsible for freeing the error message. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_IsolateMakeRunnable( + Dart_Isolate isolate); + +/* + * ================== + * Messages and Ports + * ================== + */ + +/** + * A port is used to send or receive inter-isolate messages + */ +typedef int64_t Dart_Port; + +/** + * ILLEGAL_PORT is a port number guaranteed never to be associated with a valid + * port. + */ +#define ILLEGAL_PORT ((Dart_Port)0) + +/** + * A message notification callback. + * + * This callback allows the embedder to provide an alternate wakeup + * mechanism for the delivery of inter-isolate messages. It is the + * responsibility of the embedder to call Dart_HandleMessage to + * process the message. + */ +typedef void (*Dart_MessageNotifyCallback)(Dart_Isolate dest_isolate); + +/** + * Allows embedders to provide an alternative wakeup mechanism for the + * delivery of inter-isolate messages. This setting only applies to + * the current isolate. + * + * Most embedders will only call this function once, before isolate + * execution begins. If this function is called after isolate + * execution begins, the embedder is responsible for threading issues. + */ +DART_EXPORT void Dart_SetMessageNotifyCallback( + Dart_MessageNotifyCallback message_notify_callback); +/* TODO(turnidge): Consider moving this to isolate creation so that it + * is impossible to mess up. */ + +/** + * Query the current message notify callback for the isolate. + * + * \return The current message notify callback for the isolate. + */ +DART_EXPORT Dart_MessageNotifyCallback Dart_GetMessageNotifyCallback(void); + +/** + * The VM's default message handler supports pausing an isolate before it + * processes the first message and right after the it processes the isolate's + * final message. This can be controlled for all isolates by two VM flags: + * + * `--pause-isolates-on-start` + * `--pause-isolates-on-exit` + * + * Additionally, Dart_SetShouldPauseOnStart and Dart_SetShouldPauseOnExit can be + * used to control this behaviour on a per-isolate basis. + * + * When an embedder is using a Dart_MessageNotifyCallback the embedder + * needs to cooperate with the VM so that the service protocol can report + * accurate information about isolates and so that tools such as debuggers + * work reliably. + * + * The following functions can be used to implement pausing on start and exit. + */ + +/** + * If the VM flag `--pause-isolates-on-start` was passed this will be true. + * + * \return A boolean value indicating if pause on start was requested. + */ +DART_EXPORT bool Dart_ShouldPauseOnStart(void); + +/** + * Override the VM flag `--pause-isolates-on-start` for the current isolate. + * + * \param should_pause Should the isolate be paused on start? + * + * NOTE: This must be called before Dart_IsolateMakeRunnable. + */ +DART_EXPORT void Dart_SetShouldPauseOnStart(bool should_pause); + +/** + * Is the current isolate paused on start? + * + * \return A boolean value indicating if the isolate is paused on start. + */ +DART_EXPORT bool Dart_IsPausedOnStart(void); + +/** + * Called when the embedder has paused the current isolate on start and when + * the embedder has resumed the isolate. + * + * \param paused Is the isolate paused on start? + */ +DART_EXPORT void Dart_SetPausedOnStart(bool paused); + +/** + * If the VM flag `--pause-isolates-on-exit` was passed this will be true. + * + * \return A boolean value indicating if pause on exit was requested. + */ +DART_EXPORT bool Dart_ShouldPauseOnExit(void); + +/** + * Override the VM flag `--pause-isolates-on-exit` for the current isolate. + * + * \param should_pause Should the isolate be paused on exit? + * + */ +DART_EXPORT void Dart_SetShouldPauseOnExit(bool should_pause); + +/** + * Is the current isolate paused on exit? + * + * \return A boolean value indicating if the isolate is paused on exit. + */ +DART_EXPORT bool Dart_IsPausedOnExit(void); + +/** + * Called when the embedder has paused the current isolate on exit and when + * the embedder has resumed the isolate. + * + * \param paused Is the isolate paused on exit? + */ +DART_EXPORT void Dart_SetPausedOnExit(bool paused); + +/** + * Called when the embedder has caught a top level unhandled exception error + * in the current isolate. + * + * NOTE: It is illegal to call this twice on the same isolate without first + * clearing the sticky error to null. + * + * \param error The unhandled exception error. + */ +DART_EXPORT void Dart_SetStickyError(Dart_Handle error); + +/** + * Does the current isolate have a sticky error? + */ +DART_EXPORT bool Dart_HasStickyError(void); + +/** + * Gets the sticky error for the current isolate. + * + * \return A handle to the sticky error object or null. + */ +DART_EXPORT Dart_Handle Dart_GetStickyError(void); + +/** + * Handles the next pending message for the current isolate. + * + * May generate an unhandled exception error. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_HandleMessage(void); + +/** + * Drains the microtask queue, then blocks the calling thread until the current + * isolate recieves a message, then handles all messages. + * + * \param timeout_millis When non-zero, the call returns after the indicated + number of milliseconds even if no message was received. + * \return A valid handle if no error occurs, otherwise an error handle. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_WaitForEvent(int64_t timeout_millis); + +/** + * Handles any pending messages for the vm service for the current + * isolate. + * + * This function may be used by an embedder at a breakpoint to avoid + * pausing the vm service. + * + * This function can indirectly cause the message notify callback to + * be called. + * + * \return true if the vm service requests the program resume + * execution, false otherwise + */ +DART_EXPORT bool Dart_HandleServiceMessages(void); + +/** + * Does the current isolate have pending service messages? + * + * \return true if the isolate has pending service messages, false otherwise. + */ +DART_EXPORT bool Dart_HasServiceMessages(void); + +/** + * Processes any incoming messages for the current isolate. + * + * This function may only be used when the embedder has not provided + * an alternate message delivery mechanism with + * Dart_SetMessageCallbacks. It is provided for convenience. + * + * This function waits for incoming messages for the current + * isolate. As new messages arrive, they are handled using + * Dart_HandleMessage. The routine exits when all ports to the + * current isolate are closed. + * + * \return A valid handle if the run loop exited successfully. If an + * exception or other error occurs while processing messages, an + * error handle is returned. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_RunLoop(void); + +/** + * Lets the VM run message processing for the isolate. + * + * This function expects there to a current isolate and the current isolate + * must not have an active api scope. The VM will take care of making the + * isolate runnable (if not already), handles its message loop and will take + * care of shutting the isolate down once it's done. + * + * \param errors_are_fatal Whether uncaught errors should be fatal. + * \param on_error_port A port to notify on uncaught errors (or ILLEGAL_PORT). + * \param on_exit_port A port to notify on exit (or ILLEGAL_PORT). + * \param error A non-NULL pointer which will hold an error message if the call + * fails. The error has to be free()ed by the caller. + * + * \return If successfull the VM takes owernship of the isolate and takes care + * of its message loop. If not successful the caller retains owernship of the + * isolate. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT bool Dart_RunLoopAsync( + bool errors_are_fatal, + Dart_Port on_error_port, + Dart_Port on_exit_port, + char** error); + +/* TODO(turnidge): Should this be removed from the public api? */ + +/** + * Gets the main port id for the current isolate. + */ +DART_EXPORT Dart_Port Dart_GetMainPortId(void); + +/** + * Does the current isolate have live ReceivePorts? + * + * A ReceivePort is live when it has not been closed. + */ +DART_EXPORT bool Dart_HasLivePorts(void); + +/** + * Posts a message for some isolate. The message is a serialized + * object. + * + * Requires there to be a current isolate. + * + * \param port_id The destination port. + * \param object An object from the current isolate. + * + * \return True if the message was posted. + */ +DART_EXPORT bool Dart_Post(Dart_Port port_id, Dart_Handle object); + +/** + * Returns a new SendPort with the provided port id. + * + * \param port_id The destination port. + * + * \return A new SendPort if no errors occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id); + +/** + * Gets the SendPort id for the provided SendPort. + * \param port A SendPort object whose id is desired. + * \param port_id Returns the id of the SendPort. + * \return Success if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_SendPortGetId(Dart_Handle port, + Dart_Port* port_id); + +/* + * ====== + * Scopes + * ====== + */ + +/** + * Enters a new scope. + * + * All new local handles will be created in this scope. Additionally, + * some functions may return "scope allocated" memory which is only + * valid within this scope. + * + * Requires there to be a current isolate. + */ +DART_EXPORT void Dart_EnterScope(void); + +/** + * Exits a scope. + * + * The previous scope (if any) becomes the current scope. + * + * Requires there to be a current isolate. + */ +DART_EXPORT void Dart_ExitScope(void); + +/** + * The Dart VM uses "zone allocation" for temporary structures. Zones + * support very fast allocation of small chunks of memory. The chunks + * cannot be deallocated individually, but instead zones support + * deallocating all chunks in one fast operation. + * + * This function makes it possible for the embedder to allocate + * temporary data in the VMs zone allocator. + * + * Zone allocation is possible: + * 1. when inside a scope where local handles can be allocated + * 2. when processing a message from a native port in a native port + * handler + * + * All the memory allocated this way will be reclaimed either on the + * next call to Dart_ExitScope or when the native port handler exits. + * + * \param size Size of the memory to allocate. + * + * \return A pointer to the allocated memory. NULL if allocation + * failed. Failure might due to is no current VM zone. + */ +DART_EXPORT uint8_t* Dart_ScopeAllocate(intptr_t size); + +/* + * ======= + * Objects + * ======= + */ + +/** + * Returns the null object. + * + * \return A handle to the null object. + */ +DART_EXPORT Dart_Handle Dart_Null(void); + +/** + * Is this object null? + */ +DART_EXPORT bool Dart_IsNull(Dart_Handle object); + +/** + * Returns the empty string object. + * + * \return A handle to the empty string object. + */ +DART_EXPORT Dart_Handle Dart_EmptyString(void); + +/** + * Returns types that are not classes, and which therefore cannot be looked up + * as library members by Dart_GetType. + * + * \return A handle to the dynamic, void or Never type. + */ +DART_EXPORT Dart_Handle Dart_TypeDynamic(void); +DART_EXPORT Dart_Handle Dart_TypeVoid(void); +DART_EXPORT Dart_Handle Dart_TypeNever(void); + +/** + * Checks if the two objects are equal. + * + * The result of the comparison is returned through the 'equal' + * parameter. The return value itself is used to indicate success or + * failure, not equality. + * + * May generate an unhandled exception error. + * + * \param obj1 An object to be compared. + * \param obj2 An object to be compared. + * \param equal Returns the result of the equality comparison. + * + * \return A valid handle if no error occurs during the comparison. + */ +DART_EXPORT Dart_Handle Dart_ObjectEquals(Dart_Handle obj1, + Dart_Handle obj2, + bool* equal); + +/** + * Is this object an instance of some type? + * + * The result of the test is returned through the 'instanceof' parameter. + * The return value itself is used to indicate success or failure. + * + * \param object An object. + * \param type A type. + * \param instanceof Return true if 'object' is an instance of type 'type'. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_ObjectIsType(Dart_Handle object, + Dart_Handle type, + bool* instanceof); + +/** + * Query object type. + * + * \param object Some Object. + * + * \return true if Object is of the specified type. + */ +DART_EXPORT bool Dart_IsInstance(Dart_Handle object); +DART_EXPORT bool Dart_IsNumber(Dart_Handle object); +DART_EXPORT bool Dart_IsInteger(Dart_Handle object); +DART_EXPORT bool Dart_IsDouble(Dart_Handle object); +DART_EXPORT bool Dart_IsBoolean(Dart_Handle object); +DART_EXPORT bool Dart_IsString(Dart_Handle object); +DART_EXPORT bool Dart_IsStringLatin1(Dart_Handle object); /* (ISO-8859-1) */ +DART_EXPORT bool Dart_IsExternalString(Dart_Handle object); +DART_EXPORT bool Dart_IsList(Dart_Handle object); +DART_EXPORT bool Dart_IsMap(Dart_Handle object); +DART_EXPORT bool Dart_IsLibrary(Dart_Handle object); +DART_EXPORT bool Dart_IsType(Dart_Handle handle); +DART_EXPORT bool Dart_IsFunction(Dart_Handle handle); +DART_EXPORT bool Dart_IsVariable(Dart_Handle handle); +DART_EXPORT bool Dart_IsTypeVariable(Dart_Handle handle); +DART_EXPORT bool Dart_IsClosure(Dart_Handle object); +DART_EXPORT bool Dart_IsTypedData(Dart_Handle object); +DART_EXPORT bool Dart_IsByteBuffer(Dart_Handle object); +DART_EXPORT bool Dart_IsFuture(Dart_Handle object); + +/* + * ========= + * Instances + * ========= + */ + +/* + * For the purposes of the embedding api, not all objects returned are + * Dart language objects. Within the api, we use the term 'Instance' + * to indicate handles which refer to true Dart language objects. + * + * TODO(turnidge): Reorganize the "Object" section above, pulling down + * any functions that more properly belong here. */ + +/** + * Gets the type of a Dart language object. + * + * \param instance Some Dart object. + * + * \return If no error occurs, the type is returned. Otherwise an + * error handle is returned. + */ +DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance); + +/** + * Returns the name for the provided class type. + * + * \return A valid string handle if no error occurs during the + * operation. + */ +DART_EXPORT Dart_Handle Dart_ClassName(Dart_Handle cls_type); + +/** + * Returns the name for the provided function or method. + * + * \return A valid string handle if no error occurs during the + * operation. + */ +DART_EXPORT Dart_Handle Dart_FunctionName(Dart_Handle function); + +/** + * Returns a handle to the owner of a function. + * + * The owner of an instance method or a static method is its defining + * class. The owner of a top-level function is its defining + * library. The owner of the function of a non-implicit closure is the + * function of the method or closure that defines the non-implicit + * closure. + * + * \return A valid handle to the owner of the function, or an error + * handle if the argument is not a valid handle to a function. + */ +DART_EXPORT Dart_Handle Dart_FunctionOwner(Dart_Handle function); + +/** + * Determines whether a function handle referes to a static function + * of method. + * + * For the purposes of the embedding API, a top-level function is + * implicitly declared static. + * + * \param function A handle to a function or method declaration. + * \param is_static Returns whether the function or method is declared static. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_FunctionIsStatic(Dart_Handle function, + bool* is_static); + +/** + * Is this object a closure resulting from a tear-off (closurized method)? + * + * Returns true for closures produced when an ordinary method is accessed + * through a getter call. Returns false otherwise, in particular for closures + * produced from local function declarations. + * + * \param object Some Object. + * + * \return true if Object is a tear-off. + */ +DART_EXPORT bool Dart_IsTearOff(Dart_Handle object); + +/** + * Retrieves the function of a closure. + * + * \return A handle to the function of the closure, or an error handle if the + * argument is not a closure. + */ +DART_EXPORT Dart_Handle Dart_ClosureFunction(Dart_Handle closure); + +/** + * Returns a handle to the library which contains class. + * + * \return A valid handle to the library with owns class, null if the class + * has no library or an error handle if the argument is not a valid handle + * to a class type. + */ +DART_EXPORT Dart_Handle Dart_ClassLibrary(Dart_Handle cls_type); + +/* + * ============================= + * Numbers, Integers and Doubles + * ============================= + */ + +/** + * Does this Integer fit into a 64-bit signed integer? + * + * \param integer An integer. + * \param fits Returns true if the integer fits into a 64-bit signed integer. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_IntegerFitsIntoInt64(Dart_Handle integer, + bool* fits); + +/** + * Does this Integer fit into a 64-bit unsigned integer? + * + * \param integer An integer. + * \param fits Returns true if the integer fits into a 64-bit unsigned integer. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_IntegerFitsIntoUint64(Dart_Handle integer, + bool* fits); + +/** + * Returns an Integer with the provided value. + * + * \param value The value of the integer. + * + * \return The Integer object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value); + +/** + * Returns an Integer with the provided value. + * + * \param value The unsigned value of the integer. + * + * \return The Integer object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewIntegerFromUint64(uint64_t value); + +/** + * Returns an Integer with the provided value. + * + * \param value The value of the integer represented as a C string + * containing a hexadecimal number. + * + * \return The Integer object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewIntegerFromHexCString(const char* value); + +/** + * Gets the value of an Integer. + * + * The integer must fit into a 64-bit signed integer, otherwise an error occurs. + * + * \param integer An Integer. + * \param value Returns the value of the Integer. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_IntegerToInt64(Dart_Handle integer, + int64_t* value); + +/** + * Gets the value of an Integer. + * + * The integer must fit into a 64-bit unsigned integer, otherwise an + * error occurs. + * + * \param integer An Integer. + * \param value Returns the value of the Integer. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_IntegerToUint64(Dart_Handle integer, + uint64_t* value); + +/** + * Gets the value of an integer as a hexadecimal C string. + * + * \param integer An Integer. + * \param value Returns the value of the Integer as a hexadecimal C + * string. This C string is scope allocated and is only valid until + * the next call to Dart_ExitScope. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_IntegerToHexCString(Dart_Handle integer, + const char** value); + +/** + * Returns a Double with the provided value. + * + * \param value A double. + * + * \return The Double object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewDouble(double value); + +/** + * Gets the value of a Double + * + * \param double_obj A Double + * \param value Returns the value of the Double. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_DoubleValue(Dart_Handle double_obj, double* value); + +/** + * Returns a closure of static function 'function_name' in the class 'class_name' + * in the exported namespace of specified 'library'. + * + * \param library Library object + * \param cls_type Type object representing a Class + * \param function_name Name of the static function in the class + * + * \return A valid Dart instance if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_GetStaticMethodClosure(Dart_Handle library, + Dart_Handle cls_type, + Dart_Handle function_name); + +/* + * ======== + * Booleans + * ======== + */ + +/** + * Returns the True object. + * + * Requires there to be a current isolate. + * + * \return A handle to the True object. + */ +DART_EXPORT Dart_Handle Dart_True(void); + +/** + * Returns the False object. + * + * Requires there to be a current isolate. + * + * \return A handle to the False object. + */ +DART_EXPORT Dart_Handle Dart_False(void); + +/** + * Returns a Boolean with the provided value. + * + * \param value true or false. + * + * \return The Boolean object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewBoolean(bool value); + +/** + * Gets the value of a Boolean + * + * \param boolean_obj A Boolean + * \param value Returns the value of the Boolean. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_BooleanValue(Dart_Handle boolean_obj, bool* value); + +/* + * ======= + * Strings + * ======= + */ + +/** + * Gets the length of a String. + * + * \param str A String. + * \param length Returns the length of the String. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_StringLength(Dart_Handle str, intptr_t* length); + +/** + * Returns a String built from the provided C string + * (There is an implicit assumption that the C string passed in contains + * UTF-8 encoded characters and '\0' is considered as a termination + * character). + * + * \param str A C String + * + * \return The String object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char* str); +/* TODO(turnidge): Document what happens when we run out of memory + * during this call. */ + +/** + * Returns a String built from an array of UTF-8 encoded characters. + * + * \param utf8_array An array of UTF-8 encoded characters. + * \param length The length of the codepoints array. + * + * \return The String object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewStringFromUTF8(const uint8_t* utf8_array, + intptr_t length); + +/** + * Returns a String built from an array of UTF-16 encoded characters. + * + * \param utf16_array An array of UTF-16 encoded characters. + * \param length The length of the codepoints array. + * + * \return The String object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewStringFromUTF16(const uint16_t* utf16_array, + intptr_t length); + +/** + * Returns a String built from an array of UTF-32 encoded characters. + * + * \param utf32_array An array of UTF-32 encoded characters. + * \param length The length of the codepoints array. + * + * \return The String object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewStringFromUTF32(const int32_t* utf32_array, + intptr_t length); + +/** + * Returns a String which references an external array of + * Latin-1 (ISO-8859-1) encoded characters. + * + * \param latin1_array Array of Latin-1 encoded characters. This must not move. + * \param length The length of the characters array. + * \param peer An external pointer to associate with this string. + * \param external_allocation_size The number of externally allocated + * bytes for peer. Used to inform the garbage collector. + * \param callback A callback to be called when this string is finalized. + * + * \return The String object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle +Dart_NewExternalLatin1String(const uint8_t* latin1_array, + intptr_t length, + void* peer, + intptr_t external_allocation_size, + Dart_HandleFinalizer callback); + +/** + * Returns a String which references an external array of UTF-16 encoded + * characters. + * + * \param utf16_array An array of UTF-16 encoded characters. This must not move. + * \param length The length of the characters array. + * \param peer An external pointer to associate with this string. + * \param external_allocation_size The number of externally allocated + * bytes for peer. Used to inform the garbage collector. + * \param callback A callback to be called when this string is finalized. + * + * \return The String object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle +Dart_NewExternalUTF16String(const uint16_t* utf16_array, + intptr_t length, + void* peer, + intptr_t external_allocation_size, + Dart_HandleFinalizer callback); + +/** + * Gets the C string representation of a String. + * (It is a sequence of UTF-8 encoded values with a '\0' termination.) + * + * \param str A string. + * \param cstr Returns the String represented as a C string. + * This C string is scope allocated and is only valid until + * the next call to Dart_ExitScope. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle str, + const char** cstr); + +/** + * Gets a UTF-8 encoded representation of a String. + * + * Any unpaired surrogate code points in the string will be converted as + * replacement characters (U+FFFD, 0xEF 0xBF 0xBD in UTF-8). If you need + * to preserve unpaired surrogates, use the Dart_StringToUTF16 function. + * + * \param str A string. + * \param utf8_array Returns the String represented as UTF-8 code + * units. This UTF-8 array is scope allocated and is only valid + * until the next call to Dart_ExitScope. + * \param length Used to return the length of the array which was + * actually used. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_StringToUTF8(Dart_Handle str, + uint8_t** utf8_array, + intptr_t* length); + +/** + * Gets the data corresponding to the string object. This function returns + * the data only for Latin-1 (ISO-8859-1) string objects. For all other + * string objects it returns an error. + * + * \param str A string. + * \param latin1_array An array allocated by the caller, used to return + * the string data. + * \param length Used to pass in the length of the provided array. + * Used to return the length of the array which was actually used. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_StringToLatin1(Dart_Handle str, + uint8_t* latin1_array, + intptr_t* length); + +/** + * Gets the UTF-16 encoded representation of a string. + * + * \param str A string. + * \param utf16_array An array allocated by the caller, used to return + * the array of UTF-16 encoded characters. + * \param length Used to pass in the length of the provided array. + * Used to return the length of the array which was actually used. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_StringToUTF16(Dart_Handle str, + uint16_t* utf16_array, + intptr_t* length); + +/** + * Gets the storage size in bytes of a String. + * + * \param str A String. + * \param size Returns the storage size in bytes of the String. + * This is the size in bytes needed to store the String. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_StringStorageSize(Dart_Handle str, intptr_t* size); + +/** + * Retrieves some properties associated with a String. + * Properties retrieved are: + * - character size of the string (one or two byte) + * - length of the string + * - peer pointer of string if it is an external string. + * \param str A String. + * \param char_size Returns the character size of the String. + * \param str_len Returns the length of the String. + * \param peer Returns the peer pointer associated with the String or 0 if + * there is no peer pointer for it. + * \return Success if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_StringGetProperties(Dart_Handle str, + intptr_t* char_size, + intptr_t* str_len, + void** peer); + +/* + * ===== + * Lists + * ===== + */ + +/** + * Returns a List of the desired length. + * + * \param length The length of the list. + * + * \return The List object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewList(intptr_t length); + +typedef enum { + Dart_CoreType_Dynamic, + Dart_CoreType_Int, + Dart_CoreType_String, +} Dart_CoreType_Id; + +// TODO(bkonyi): convert this to use nullable types once NNBD is enabled. +/** + * Returns a List of the desired length with the desired legacy element type. + * + * \param element_type_id The type of elements of the list. + * \param length The length of the list. + * + * \return The List object if no error occurs. Otherwise returns an error + * handle. + */ +DART_EXPORT Dart_Handle Dart_NewListOf(Dart_CoreType_Id element_type_id, + intptr_t length); + +/** + * Returns a List of the desired length with the desired element type. + * + * \param element_type Handle to a nullable type object. E.g., from + * Dart_GetType or Dart_GetNullableType. + * + * \param length The length of the list. + * + * \return The List object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewListOfType(Dart_Handle element_type, + intptr_t length); + +/** + * Returns a List of the desired length with the desired element type, filled + * with the provided object. + * + * \param element_type Handle to a type object. E.g., from Dart_GetType. + * + * \param fill_object Handle to an object of type 'element_type' that will be + * used to populate the list. This parameter can only be Dart_Null() if the + * length of the list is 0 or 'element_type' is a nullable type. + * + * \param length The length of the list. + * + * \return The List object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewListOfTypeFilled(Dart_Handle element_type, + Dart_Handle fill_object, + intptr_t length); + +/** + * Gets the length of a List. + * + * May generate an unhandled exception error. + * + * \param list A List. + * \param length Returns the length of the List. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_ListLength(Dart_Handle list, intptr_t* length); + +/** + * Gets the Object at some index of a List. + * + * If the index is out of bounds, an error occurs. + * + * May generate an unhandled exception error. + * + * \param list A List. + * \param index A valid index into the List. + * + * \return The Object in the List at the specified index if no error + * occurs. Otherwise returns an error handle. + */ +DART_EXPORT Dart_Handle Dart_ListGetAt(Dart_Handle list, intptr_t index); + +/** +* Gets a range of Objects from a List. +* +* If any of the requested index values are out of bounds, an error occurs. +* +* May generate an unhandled exception error. +* +* \param list A List. +* \param offset The offset of the first item to get. +* \param length The number of items to get. +* \param result A pointer to fill with the objects. +* +* \return Success if no error occurs during the operation. +*/ +DART_EXPORT Dart_Handle Dart_ListGetRange(Dart_Handle list, + intptr_t offset, + intptr_t length, + Dart_Handle* result); + +/** + * Sets the Object at some index of a List. + * + * If the index is out of bounds, an error occurs. + * + * May generate an unhandled exception error. + * + * \param list A List. + * \param index A valid index into the List. + * \param value The Object to put in the List. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list, + intptr_t index, + Dart_Handle value); + +/** + * May generate an unhandled exception error. + */ +DART_EXPORT Dart_Handle Dart_ListGetAsBytes(Dart_Handle list, + intptr_t offset, + uint8_t* native_array, + intptr_t length); + +/** + * May generate an unhandled exception error. + */ +DART_EXPORT Dart_Handle Dart_ListSetAsBytes(Dart_Handle list, + intptr_t offset, + const uint8_t* native_array, + intptr_t length); + +/* + * ==== + * Maps + * ==== + */ + +/** + * Gets the Object at some key of a Map. + * + * May generate an unhandled exception error. + * + * \param map A Map. + * \param key An Object. + * + * \return The value in the map at the specified key, null if the map does not + * contain the key, or an error handle. + */ +DART_EXPORT Dart_Handle Dart_MapGetAt(Dart_Handle map, Dart_Handle key); + +/** + * Returns whether the Map contains a given key. + * + * May generate an unhandled exception error. + * + * \param map A Map. + * + * \return A handle on a boolean indicating whether map contains the key. + * Otherwise returns an error handle. + */ +DART_EXPORT Dart_Handle Dart_MapContainsKey(Dart_Handle map, Dart_Handle key); + +/** + * Gets the list of keys of a Map. + * + * May generate an unhandled exception error. + * + * \param map A Map. + * + * \return The list of key Objects if no error occurs. Otherwise returns an + * error handle. + */ +DART_EXPORT Dart_Handle Dart_MapKeys(Dart_Handle map); + +/* + * ========== + * Typed Data + * ========== + */ + +typedef enum { + Dart_TypedData_kByteData = 0, + Dart_TypedData_kInt8, + Dart_TypedData_kUint8, + Dart_TypedData_kUint8Clamped, + Dart_TypedData_kInt16, + Dart_TypedData_kUint16, + Dart_TypedData_kInt32, + Dart_TypedData_kUint32, + Dart_TypedData_kInt64, + Dart_TypedData_kUint64, + Dart_TypedData_kFloat32, + Dart_TypedData_kFloat64, + Dart_TypedData_kInt32x4, + Dart_TypedData_kFloat32x4, + Dart_TypedData_kFloat64x2, + Dart_TypedData_kInvalid +} Dart_TypedData_Type; + +/** + * Return type if this object is a TypedData object. + * + * \return kInvalid if the object is not a TypedData object or the appropriate + * Dart_TypedData_Type. + */ +DART_EXPORT Dart_TypedData_Type Dart_GetTypeOfTypedData(Dart_Handle object); + +/** + * Return type if this object is an external TypedData object. + * + * \return kInvalid if the object is not an external TypedData object or + * the appropriate Dart_TypedData_Type. + */ +DART_EXPORT Dart_TypedData_Type +Dart_GetTypeOfExternalTypedData(Dart_Handle object); + +/** + * Returns a TypedData object of the desired length and type. + * + * \param type The type of the TypedData object. + * \param length The length of the TypedData object (length in type units). + * + * \return The TypedData object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewTypedData(Dart_TypedData_Type type, + intptr_t length); + +/** + * Returns a TypedData object which references an external data array. + * + * \param type The type of the data array. + * \param data A data array. This array must not move. + * \param length The length of the data array (length in type units). + * + * \return The TypedData object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewExternalTypedData(Dart_TypedData_Type type, + void* data, + intptr_t length); + +/** + * Returns a TypedData object which references an external data array. + * + * \param type The type of the data array. + * \param data A data array. This array must not move. + * \param length The length of the data array (length in type units). + * \param peer A pointer to a native object or NULL. This value is + * provided to callback when it is invoked. + * \param external_allocation_size The number of externally allocated + * bytes for peer. Used to inform the garbage collector. + * \param callback A function pointer that will be invoked sometime + * after the object is garbage collected, unless the handle has been deleted. + * A valid callback needs to be specified it cannot be NULL. + * + * \return The TypedData object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle +Dart_NewExternalTypedDataWithFinalizer(Dart_TypedData_Type type, + void* data, + intptr_t length, + void* peer, + intptr_t external_allocation_size, + Dart_HandleFinalizer callback); + +/** + * Returns a ByteBuffer object for the typed data. + * + * \param typed_data The TypedData object. + * + * \return The ByteBuffer object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewByteBuffer(Dart_Handle typed_data); + +/** + * Acquires access to the internal data address of a TypedData object. + * + * \param object The typed data object whose internal data address is to + * be accessed. + * \param type The type of the object is returned here. + * \param data The internal data address is returned here. + * \param len Size of the typed array is returned here. + * + * Notes: + * When the internal address of the object is acquired any calls to a + * Dart API function that could potentially allocate an object or run + * any Dart code will return an error. + * + * Any Dart API functions for accessing the data should not be called + * before the corresponding release. In particular, the object should + * not be acquired again before its release. This leads to undefined + * behavior. + * + * \return Success if the internal data address is acquired successfully. + * Otherwise, returns an error handle. + */ +DART_EXPORT Dart_Handle Dart_TypedDataAcquireData(Dart_Handle object, + Dart_TypedData_Type* type, + void** data, + intptr_t* len); + +/** + * Releases access to the internal data address that was acquired earlier using + * Dart_TypedDataAcquireData. + * + * \param object The typed data object whose internal data address is to be + * released. + * + * \return Success if the internal data address is released successfully. + * Otherwise, returns an error handle. + */ +DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object); + +/** + * Returns the TypedData object associated with the ByteBuffer object. + * + * \param byte_buffer The ByteBuffer object. + * + * \return The TypedData object if no error occurs. Otherwise returns + * an error handle. + */ +DART_EXPORT Dart_Handle Dart_GetDataFromByteBuffer(Dart_Handle byte_buffer); + +/* + * ============================================================ + * Invoking Constructors, Methods, Closures and Field accessors + * ============================================================ + */ + +/** + * Invokes a constructor, creating a new object. + * + * This function allows hidden constructors (constructors with leading + * underscores) to be called. + * + * \param type Type of object to be constructed. + * \param constructor_name The name of the constructor to invoke. Use + * Dart_Null() or Dart_EmptyString() to invoke the unnamed constructor. + * This name should not include the name of the class. + * \param number_of_arguments Size of the arguments array. + * \param arguments An array of arguments to the constructor. + * + * \return If the constructor is called and completes successfully, + * then the new object. If an error occurs during execution, then an + * error handle is returned. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_New(Dart_Handle type, + Dart_Handle constructor_name, + int number_of_arguments, + Dart_Handle* arguments); + +/** + * Allocate a new object without invoking a constructor. + * + * \param type The type of an object to be allocated. + * + * \return The new object. If an error occurs during execution, then an + * error handle is returned. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_Allocate(Dart_Handle type); + +/** + * Allocate a new object without invoking a constructor, and sets specified + * native fields. + * + * \param type The type of an object to be allocated. + * \param num_native_fields The number of native fields to set. + * \param native_fields An array containing the value of native fields. + * + * \return The new object. If an error occurs during execution, then an + * error handle is returned. + */ +DART_EXPORT Dart_Handle +Dart_AllocateWithNativeFields(Dart_Handle type, + intptr_t num_native_fields, + const intptr_t* native_fields); + +/** + * Invokes a method or function. + * + * The 'target' parameter may be an object, type, or library. If + * 'target' is an object, then this function will invoke an instance + * method. If 'target' is a type, then this function will invoke a + * static method. If 'target' is a library, then this function will + * invoke a top-level function from that library. + * NOTE: This API call cannot be used to invoke methods of a type object. + * + * This function ignores visibility (leading underscores in names). + * + * May generate an unhandled exception error. + * + * \param target An object, type, or library. + * \param name The name of the function or method to invoke. + * \param number_of_arguments Size of the arguments array. + * \param arguments An array of arguments to the function. + * + * \return If the function or method is called and completes + * successfully, then the return value is returned. If an error + * occurs during execution, then an error handle is returned. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_Invoke(Dart_Handle target, + Dart_Handle name, + int number_of_arguments, + Dart_Handle* arguments); +/* TODO(turnidge): Document how to invoke operators. */ + +/** + * Invokes a Closure with the given arguments. + * + * May generate an unhandled exception error. + * + * \return If no error occurs during execution, then the result of + * invoking the closure is returned. If an error occurs during + * execution, then an error handle is returned. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_InvokeClosure(Dart_Handle closure, + int number_of_arguments, + Dart_Handle* arguments); + +/** + * Invokes a Generative Constructor on an object that was previously + * allocated using Dart_Allocate/Dart_AllocateWithNativeFields. + * + * The 'object' parameter must be an object. + * + * This function ignores visibility (leading underscores in names). + * + * May generate an unhandled exception error. + * + * \param object An object. + * \param name The name of the constructor to invoke. + * Use Dart_Null() or Dart_EmptyString() to invoke the unnamed constructor. + * \param number_of_arguments Size of the arguments array. + * \param arguments An array of arguments to the function. + * + * \return If the constructor is called and completes + * successfully, then the object is returned. If an error + * occurs during execution, then an error handle is returned. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_InvokeConstructor(Dart_Handle object, + Dart_Handle name, + int number_of_arguments, + Dart_Handle* arguments); + +/** + * Gets the value of a field. + * + * The 'container' parameter may be an object, type, or library. If + * 'container' is an object, then this function will access an + * instance field. If 'container' is a type, then this function will + * access a static field. If 'container' is a library, then this + * function will access a top-level variable. + * NOTE: This API call cannot be used to access fields of a type object. + * + * This function ignores field visibility (leading underscores in names). + * + * May generate an unhandled exception error. + * + * \param container An object, type, or library. + * \param name A field name. + * + * \return If no error occurs, then the value of the field is + * returned. Otherwise an error handle is returned. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_GetField(Dart_Handle container, Dart_Handle name); + +/** + * Sets the value of a field. + * + * The 'container' parameter may actually be an object, type, or + * library. If 'container' is an object, then this function will + * access an instance field. If 'container' is a type, then this + * function will access a static field. If 'container' is a library, + * then this function will access a top-level variable. + * NOTE: This API call cannot be used to access fields of a type object. + * + * This function ignores field visibility (leading underscores in names). + * + * May generate an unhandled exception error. + * + * \param container An object, type, or library. + * \param name A field name. + * \param value The new field value. + * + * \return A valid handle if no error occurs. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_SetField(Dart_Handle container, Dart_Handle name, Dart_Handle value); + +/* + * ========== + * Exceptions + * ========== + */ + +/* + * TODO(turnidge): Remove these functions from the api and replace all + * uses with Dart_NewUnhandledExceptionError. */ + +/** + * Throws an exception. + * + * This function causes a Dart language exception to be thrown. This + * will proceed in the standard way, walking up Dart frames until an + * appropriate 'catch' block is found, executing 'finally' blocks, + * etc. + * + * If an error handle is passed into this function, the error is + * propagated immediately. See Dart_PropagateError for a discussion + * of error propagation. + * + * If successful, this function does not return. Note that this means + * that the destructors of any stack-allocated C++ objects will not be + * called. If there are no Dart frames on the stack, an error occurs. + * + * \return An error handle if the exception was not thrown. + * Otherwise the function does not return. + */ +DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception); + +/** + * Rethrows an exception. + * + * Rethrows an exception, unwinding all dart frames on the stack. If + * successful, this function does not return. Note that this means + * that the destructors of any stack-allocated C++ objects will not be + * called. If there are no Dart frames on the stack, an error occurs. + * + * \return An error handle if the exception was not thrown. + * Otherwise the function does not return. + */ +DART_EXPORT Dart_Handle Dart_ReThrowException(Dart_Handle exception, + Dart_Handle stacktrace); + +/* + * =========================== + * Native fields and functions + * =========================== + */ + +/** + * Gets the number of native instance fields in an object. + */ +DART_EXPORT Dart_Handle Dart_GetNativeInstanceFieldCount(Dart_Handle obj, + int* count); + +/** + * Gets the value of a native field. + * + * TODO(turnidge): Document. + */ +DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj, + int index, + intptr_t* value); + +/** + * Sets the value of a native field. + * + * TODO(turnidge): Document. + */ +DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj, + int index, + intptr_t value); + +/** + * The arguments to a native function. + * + * This object is passed to a native function to represent its + * arguments and return value. It allows access to the arguments to a + * native function by index. It also allows the return value of a + * native function to be set. + */ +typedef struct _Dart_NativeArguments* Dart_NativeArguments; + +/** + * Extracts current isolate group data from the native arguments structure. + */ +DART_EXPORT void* Dart_GetNativeIsolateGroupData(Dart_NativeArguments args); + +typedef enum { + Dart_NativeArgument_kBool = 0, + Dart_NativeArgument_kInt32, + Dart_NativeArgument_kUint32, + Dart_NativeArgument_kInt64, + Dart_NativeArgument_kUint64, + Dart_NativeArgument_kDouble, + Dart_NativeArgument_kString, + Dart_NativeArgument_kInstance, + Dart_NativeArgument_kNativeFields, +} Dart_NativeArgument_Type; + +typedef struct _Dart_NativeArgument_Descriptor { + uint8_t type; + uint8_t index; +} Dart_NativeArgument_Descriptor; + +typedef union _Dart_NativeArgument_Value { + bool as_bool; + int32_t as_int32; + uint32_t as_uint32; + int64_t as_int64; + uint64_t as_uint64; + double as_double; + struct { + Dart_Handle dart_str; + void* peer; + } as_string; + struct { + intptr_t num_fields; + intptr_t* values; + } as_native_fields; + Dart_Handle as_instance; +} Dart_NativeArgument_Value; + +enum { + kNativeArgNumberPos = 0, + kNativeArgNumberSize = 8, + kNativeArgTypePos = kNativeArgNumberPos + kNativeArgNumberSize, + kNativeArgTypeSize = 8, +}; + +#define BITMASK(size) ((1 << size) - 1) +#define DART_NATIVE_ARG_DESCRIPTOR(type, position) \ + (((type & BITMASK(kNativeArgTypeSize)) << kNativeArgTypePos) | \ + (position & BITMASK(kNativeArgNumberSize))) + +/** + * Gets the native arguments based on the types passed in and populates + * the passed arguments buffer with appropriate native values. + * + * \param args the Native arguments block passed into the native call. + * \param num_arguments length of argument descriptor array and argument + * values array passed in. + * \param arg_descriptors an array that describes the arguments that + * need to be retrieved. For each argument to be retrieved the descriptor + * contains the argument number (0, 1 etc.) and the argument type + * described using Dart_NativeArgument_Type, e.g: + * DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kBool, 1) indicates + * that the first argument is to be retrieved and it should be a boolean. + * \param arg_values array into which the native arguments need to be + * extracted into, the array is allocated by the caller (it could be + * stack allocated to avoid the malloc/free performance overhead). + * + * \return Success if all the arguments could be extracted correctly, + * returns an error handle if there were any errors while extracting the + * arguments (mismatched number of arguments, incorrect types, etc.). + */ +DART_EXPORT Dart_Handle +Dart_GetNativeArguments(Dart_NativeArguments args, + int num_arguments, + const Dart_NativeArgument_Descriptor* arg_descriptors, + Dart_NativeArgument_Value* arg_values); + +/** + * Gets the native argument at some index. + */ +DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, + int index); +/* TODO(turnidge): Specify the behavior of an out-of-bounds access. */ + +/** + * Gets the number of native arguments. + */ +DART_EXPORT int Dart_GetNativeArgumentCount(Dart_NativeArguments args); + +/** + * Gets all the native fields of the native argument at some index. + * \param args Native arguments structure. + * \param arg_index Index of the desired argument in the structure above. + * \param num_fields size of the intptr_t array 'field_values' passed in. + * \param field_values intptr_t array in which native field values are returned. + * \return Success if the native fields where copied in successfully. Otherwise + * returns an error handle. On success the native field values are copied + * into the 'field_values' array, if the argument at 'arg_index' is a + * null object then 0 is copied as the native field values into the + * 'field_values' array. + */ +DART_EXPORT Dart_Handle +Dart_GetNativeFieldsOfArgument(Dart_NativeArguments args, + int arg_index, + int num_fields, + intptr_t* field_values); + +/** + * Gets the native field of the receiver. + */ +DART_EXPORT Dart_Handle Dart_GetNativeReceiver(Dart_NativeArguments args, + intptr_t* value); + +/** + * Gets a string native argument at some index. + * \param args Native arguments structure. + * \param arg_index Index of the desired argument in the structure above. + * \param peer Returns the peer pointer if the string argument has one. + * \return Success if the string argument has a peer, if it does not + * have a peer then the String object is returned. Otherwise returns + * an error handle (argument is not a String object). + */ +DART_EXPORT Dart_Handle Dart_GetNativeStringArgument(Dart_NativeArguments args, + int arg_index, + void** peer); + +/** + * Gets an integer native argument at some index. + * \param args Native arguments structure. + * \param index Index of the desired argument in the structure above. + * \param value Returns the integer value if the argument is an Integer. + * \return Success if no error occurs. Otherwise returns an error handle. + */ +DART_EXPORT Dart_Handle Dart_GetNativeIntegerArgument(Dart_NativeArguments args, + int index, + int64_t* value); + +/** + * Gets a boolean native argument at some index. + * \param args Native arguments structure. + * \param index Index of the desired argument in the structure above. + * \param value Returns the boolean value if the argument is a Boolean. + * \return Success if no error occurs. Otherwise returns an error handle. + */ +DART_EXPORT Dart_Handle Dart_GetNativeBooleanArgument(Dart_NativeArguments args, + int index, + bool* value); + +/** + * Gets a double native argument at some index. + * \param args Native arguments structure. + * \param index Index of the desired argument in the structure above. + * \param value Returns the double value if the argument is a double. + * \return Success if no error occurs. Otherwise returns an error handle. + */ +DART_EXPORT Dart_Handle Dart_GetNativeDoubleArgument(Dart_NativeArguments args, + int index, + double* value); + +/** + * Sets the return value for a native function. + * + * If retval is an Error handle, then error will be propagated once + * the native functions exits. See Dart_PropagateError for a + * discussion of how different types of errors are propagated. + */ +DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args, + Dart_Handle retval); + +DART_EXPORT void Dart_SetWeakHandleReturnValue(Dart_NativeArguments args, + Dart_WeakPersistentHandle rval); + +DART_EXPORT void Dart_SetBooleanReturnValue(Dart_NativeArguments args, + bool retval); + +DART_EXPORT void Dart_SetIntegerReturnValue(Dart_NativeArguments args, + int64_t retval); + +DART_EXPORT void Dart_SetDoubleReturnValue(Dart_NativeArguments args, + double retval); + +/** + * A native function. + */ +typedef void (*Dart_NativeFunction)(Dart_NativeArguments arguments); + +/** + * Native entry resolution callback. + * + * For libraries and scripts which have native functions, the embedder + * can provide a native entry resolver. This callback is used to map a + * name/arity to a Dart_NativeFunction. If no function is found, the + * callback should return NULL. + * + * The parameters to the native resolver function are: + * \param name a Dart string which is the name of the native function. + * \param num_of_arguments is the number of arguments expected by the + * native function. + * \param auto_setup_scope is a boolean flag that can be set by the resolver + * to indicate if this function needs a Dart API scope (see Dart_EnterScope/ + * Dart_ExitScope) to be setup automatically by the VM before calling into + * the native function. By default most native functions would require this + * to be true but some light weight native functions which do not call back + * into the VM through the Dart API may not require a Dart scope to be + * setup automatically. + * + * \return A valid Dart_NativeFunction which resolves to a native entry point + * for the native function. + * + * See Dart_SetNativeResolver. + */ +typedef Dart_NativeFunction (*Dart_NativeEntryResolver)(Dart_Handle name, + int num_of_arguments, + bool* auto_setup_scope); +/* TODO(turnidge): Consider renaming to NativeFunctionResolver or + * NativeResolver. */ + +/** + * Native entry symbol lookup callback. + * + * For libraries and scripts which have native functions, the embedder + * can provide a callback for mapping a native entry to a symbol. This callback + * maps a native function entry PC to the native function name. If no native + * entry symbol can be found, the callback should return NULL. + * + * The parameters to the native reverse resolver function are: + * \param nf A Dart_NativeFunction. + * + * \return A const UTF-8 string containing the symbol name or NULL. + * + * See Dart_SetNativeResolver. + */ +typedef const uint8_t* (*Dart_NativeEntrySymbol)(Dart_NativeFunction nf); + +/** + * FFI Native C function pointer resolver callback. + * + * See Dart_SetFfiNativeResolver. + */ +typedef void* (*Dart_FfiNativeResolver)(const char* name, uintptr_t args_n); + +/* + * =========== + * Environment + * =========== + */ + +/** + * An environment lookup callback function. + * + * \param name The name of the value to lookup in the environment. + * + * \return A valid handle to a string if the name exists in the + * current environment or Dart_Null() if not. + */ +typedef Dart_Handle (*Dart_EnvironmentCallback)(Dart_Handle name); + +/** + * Sets the environment callback for the current isolate. This + * callback is used to lookup environment values by name in the + * current environment. This enables the embedder to supply values for + * the const constructors bool.fromEnvironment, int.fromEnvironment + * and String.fromEnvironment. + */ +DART_EXPORT Dart_Handle +Dart_SetEnvironmentCallback(Dart_EnvironmentCallback callback); + +/** + * Sets the callback used to resolve native functions for a library. + * + * \param library A library. + * \param resolver A native entry resolver. + * + * \return A valid handle if the native resolver was set successfully. + */ +DART_EXPORT Dart_Handle +Dart_SetNativeResolver(Dart_Handle library, + Dart_NativeEntryResolver resolver, + Dart_NativeEntrySymbol symbol); +/* TODO(turnidge): Rename to Dart_LibrarySetNativeResolver? */ + +/** + * Returns the callback used to resolve native functions for a library. + * + * \param library A library. + * \param resolver a pointer to a Dart_NativeEntryResolver + * + * \return A valid handle if the library was found. + */ +DART_EXPORT Dart_Handle +Dart_GetNativeResolver(Dart_Handle library, Dart_NativeEntryResolver* resolver); + +/** + * Returns the callback used to resolve native function symbols for a library. + * + * \param library A library. + * \param resolver a pointer to a Dart_NativeEntrySymbol. + * + * \return A valid handle if the library was found. + */ +DART_EXPORT Dart_Handle Dart_GetNativeSymbol(Dart_Handle library, + Dart_NativeEntrySymbol* resolver); + +/** + * Sets the callback used to resolve FFI native functions for a library. + * The resolved functions are expected to be a C function pointer of the + * correct signature (as specified in the `@FfiNative()` function + * annotation in Dart code). + * + * NOTE: This is an experimental feature and might change in the future. + * + * \param library A library. + * \param resolver A native function resolver. + * + * \return A valid handle if the native resolver was set successfully. + */ +DART_EXPORT Dart_Handle +Dart_SetFfiNativeResolver(Dart_Handle library, Dart_FfiNativeResolver resolver); + +/* + * ===================== + * Scripts and Libraries + * ===================== + */ + +typedef enum { + Dart_kCanonicalizeUrl = 0, + Dart_kImportTag, + Dart_kKernelTag, +} Dart_LibraryTag; + +/** + * The library tag handler is a multi-purpose callback provided by the + * embedder to the Dart VM. The embedder implements the tag handler to + * provide the ability to load Dart scripts and imports. + * + * -- TAGS -- + * + * Dart_kCanonicalizeUrl + * + * This tag indicates that the embedder should canonicalize 'url' with + * respect to 'library'. For most embedders, the + * Dart_DefaultCanonicalizeUrl function is a sufficient implementation + * of this tag. The return value should be a string holding the + * canonicalized url. + * + * Dart_kImportTag + * + * This tag is used to load a library from IsolateMirror.loadUri. The embedder + * should call Dart_LoadLibraryFromKernel to provide the library to the VM. The + * return value should be an error or library (the result from + * Dart_LoadLibraryFromKernel). + * + * Dart_kKernelTag + * + * This tag is used to load the intermediate file (kernel) generated by + * the Dart front end. This tag is typically used when a 'hot-reload' + * of an application is needed and the VM is 'use dart front end' mode. + * The dart front end typically compiles all the scripts, imports and part + * files into one intermediate file hence we don't use the source/import or + * script tags. The return value should be an error or a TypedData containing + * the kernel bytes. + * + */ +typedef Dart_Handle (*Dart_LibraryTagHandler)( + Dart_LibraryTag tag, + Dart_Handle library_or_package_map_url, + Dart_Handle url); + +/** + * Sets library tag handler for the current isolate. This handler is + * used to handle the various tags encountered while loading libraries + * or scripts in the isolate. + * + * \param handler Handler code to be used for handling the various tags + * encountered while loading libraries or scripts in the isolate. + * + * \return If no error occurs, the handler is set for the isolate. + * Otherwise an error handle is returned. + * + * TODO(turnidge): Document. + */ +DART_EXPORT Dart_Handle +Dart_SetLibraryTagHandler(Dart_LibraryTagHandler handler); + +/** + * Handles deferred loading requests. When this handler is invoked, it should + * eventually load the deferred loading unit with the given id and call + * Dart_DeferredLoadComplete or Dart_DeferredLoadCompleteError. It is + * recommended that the loading occur asynchronously, but it is permitted to + * call Dart_DeferredLoadComplete or Dart_DeferredLoadCompleteError before the + * handler returns. + * + * If an error is returned, it will be propogated through + * `prefix.loadLibrary()`. This is useful for synchronous + * implementations, which must propogate any unwind errors from + * Dart_DeferredLoadComplete or Dart_DeferredLoadComplete. Otherwise the handler + * should return a non-error such as `Dart_Null()`. + */ +typedef Dart_Handle (*Dart_DeferredLoadHandler)(intptr_t loading_unit_id); + +/** + * Sets the deferred load handler for the current isolate. This handler is + * used to handle loading deferred imports in an AppJIT or AppAOT program. + */ +DART_EXPORT Dart_Handle +Dart_SetDeferredLoadHandler(Dart_DeferredLoadHandler handler); + +/** + * Notifies the VM that a deferred load completed successfully. This function + * will eventually cause the corresponding `prefix.loadLibrary()` futures to + * complete. + * + * Requires the current isolate to be the same current isolate during the + * invocation of the Dart_DeferredLoadHandler. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_DeferredLoadComplete(intptr_t loading_unit_id, + const uint8_t* snapshot_data, + const uint8_t* snapshot_instructions); + +/** + * Notifies the VM that a deferred load failed. This function + * will eventually cause the corresponding `prefix.loadLibrary()` futures to + * complete with an error. + * + * If `transient` is true, future invocations of `prefix.loadLibrary()` will + * trigger new load requests. If false, futures invocation will complete with + * the same error. + * + * Requires the current isolate to be the same current isolate during the + * invocation of the Dart_DeferredLoadHandler. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_DeferredLoadCompleteError(intptr_t loading_unit_id, + const char* error_message, + bool transient); + +/** + * Canonicalizes a url with respect to some library. + * + * The url is resolved with respect to the library's url and some url + * normalizations are performed. + * + * This canonicalization function should be sufficient for most + * embedders to implement the Dart_kCanonicalizeUrl tag. + * + * \param base_url The base url relative to which the url is + * being resolved. + * \param url The url being resolved and canonicalized. This + * parameter is a string handle. + * + * \return If no error occurs, a String object is returned. Otherwise + * an error handle is returned. + */ +DART_EXPORT Dart_Handle Dart_DefaultCanonicalizeUrl(Dart_Handle base_url, + Dart_Handle url); + +/** + * Loads the root library for the current isolate. + * + * Requires there to be no current root library. + * + * \param kernel_buffer A buffer which contains a kernel binary (see + * pkg/kernel/binary.md). Must remain valid until isolate group shutdown. + * \param kernel_size Length of the passed in buffer. + * + * \return A handle to the root library, or an error. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_LoadScriptFromKernel(const uint8_t* kernel_buffer, intptr_t kernel_size); + +/** + * Gets the library for the root script for the current isolate. + * + * If the root script has not yet been set for the current isolate, + * this function returns Dart_Null(). This function never returns an + * error handle. + * + * \return Returns the root Library for the current isolate or Dart_Null(). + */ +DART_EXPORT Dart_Handle Dart_RootLibrary(void); + +/** + * Sets the root library for the current isolate. + * + * \return Returns an error handle if `library` is not a library handle. + */ +DART_EXPORT Dart_Handle Dart_SetRootLibrary(Dart_Handle library); + +/** + * Lookup or instantiate a legacy type by name and type arguments from a + * Library. + * + * \param library The library containing the class or interface. + * \param class_name The class name for the type. + * \param number_of_type_arguments Number of type arguments. + * For non parametric types the number of type arguments would be 0. + * \param type_arguments Pointer to an array of type arguments. + * For non parameteric types a NULL would be passed in for this argument. + * + * \return If no error occurs, the type is returned. + * Otherwise an error handle is returned. + */ +DART_EXPORT Dart_Handle Dart_GetType(Dart_Handle library, + Dart_Handle class_name, + intptr_t number_of_type_arguments, + Dart_Handle* type_arguments); + +/** + * Lookup or instantiate a nullable type by name and type arguments from + * Library. + * + * \param library The library containing the class or interface. + * \param class_name The class name for the type. + * \param number_of_type_arguments Number of type arguments. + * For non parametric types the number of type arguments would be 0. + * \param type_arguments Pointer to an array of type arguments. + * For non parameteric types a NULL would be passed in for this argument. + * + * \return If no error occurs, the type is returned. + * Otherwise an error handle is returned. + */ +DART_EXPORT Dart_Handle Dart_GetNullableType(Dart_Handle library, + Dart_Handle class_name, + intptr_t number_of_type_arguments, + Dart_Handle* type_arguments); + +/** + * Lookup or instantiate a non-nullable type by name and type arguments from + * Library. + * + * \param library The library containing the class or interface. + * \param class_name The class name for the type. + * \param number_of_type_arguments Number of type arguments. + * For non parametric types the number of type arguments would be 0. + * \param type_arguments Pointer to an array of type arguments. + * For non parameteric types a NULL would be passed in for this argument. + * + * \return If no error occurs, the type is returned. + * Otherwise an error handle is returned. + */ +DART_EXPORT Dart_Handle +Dart_GetNonNullableType(Dart_Handle library, + Dart_Handle class_name, + intptr_t number_of_type_arguments, + Dart_Handle* type_arguments); + +/** + * Creates a nullable version of the provided type. + * + * \param type The type to be converted to a nullable type. + * + * \return If no error occurs, a nullable type is returned. + * Otherwise an error handle is returned. + */ +DART_EXPORT Dart_Handle Dart_TypeToNullableType(Dart_Handle type); + +/** + * Creates a non-nullable version of the provided type. + * + * \param type The type to be converted to a non-nullable type. + * + * \return If no error occurs, a non-nullable type is returned. + * Otherwise an error handle is returned. + */ +DART_EXPORT Dart_Handle Dart_TypeToNonNullableType(Dart_Handle type); + +/** + * A type's nullability. + * + * \param type A Dart type. + * \param result An out parameter containing the result of the check. True if + * the type is of the specified nullability, false otherwise. + * + * \return Returns an error handle if type is not of type Type. + */ +DART_EXPORT Dart_Handle Dart_IsNullableType(Dart_Handle type, bool* result); +DART_EXPORT Dart_Handle Dart_IsNonNullableType(Dart_Handle type, bool* result); +DART_EXPORT Dart_Handle Dart_IsLegacyType(Dart_Handle type, bool* result); + +/** + * Lookup a class or interface by name from a Library. + * + * \param library The library containing the class or interface. + * \param class_name The name of the class or interface. + * + * \return If no error occurs, the class or interface is + * returned. Otherwise an error handle is returned. + */ +DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library, + Dart_Handle class_name); +/* TODO(asiva): The above method needs to be removed once all uses + * of it are removed from the embedder code. */ + +/** + * Returns an import path to a Library, such as "file:///test.dart" or + * "dart:core". + */ +DART_EXPORT Dart_Handle Dart_LibraryUrl(Dart_Handle library); + +/** + * Returns a URL from which a Library was loaded. + */ +DART_EXPORT Dart_Handle Dart_LibraryResolvedUrl(Dart_Handle library); + +/** + * \return An array of libraries. + */ +DART_EXPORT Dart_Handle Dart_GetLoadedLibraries(void); + +DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url); +/* TODO(turnidge): Consider returning Dart_Null() when the library is + * not found to distinguish that from a true error case. */ + +/** + * Report an loading error for the library. + * + * \param library The library that failed to load. + * \param error The Dart error instance containing the load error. + * + * \return If the VM handles the error, the return value is + * a null handle. If it doesn't handle the error, the error + * object is returned. + */ +DART_EXPORT Dart_Handle Dart_LibraryHandleError(Dart_Handle library, + Dart_Handle error); + +/** + * Called by the embedder to load a partial program. Does not set the root + * library. + * + * \param kernel_buffer A buffer which contains a kernel binary (see + * pkg/kernel/binary.md). Must remain valid until isolate shutdown. + * \param kernel_buffer_size Length of the passed in buffer. + * + * \return A handle to the main library of the compilation unit, or an error. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_LoadLibraryFromKernel(const uint8_t* kernel_buffer, + intptr_t kernel_buffer_size); + +/** + * Indicates that all outstanding load requests have been satisfied. + * This finalizes all the new classes loaded and optionally completes + * deferred library futures. + * + * Requires there to be a current isolate. + * + * \param complete_futures Specify true if all deferred library + * futures should be completed, false otherwise. + * + * \return Success if all classes have been finalized and deferred library + * futures are completed. Otherwise, returns an error. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_FinalizeLoading(bool complete_futures); + +/* + * ===== + * Peers + * ===== + */ + +/** + * The peer field is a lazily allocated field intended for storage of + * an uncommonly used values. Most instances types can have a peer + * field allocated. The exceptions are subtypes of Null, num, and + * bool. + */ + +/** + * Returns the value of peer field of 'object' in 'peer'. + * + * \param object An object. + * \param peer An out parameter that returns the value of the peer + * field. + * + * \return Returns an error if 'object' is a subtype of Null, num, or + * bool. + */ +DART_EXPORT Dart_Handle Dart_GetPeer(Dart_Handle object, void** peer); + +/** + * Sets the value of the peer field of 'object' to the value of + * 'peer'. + * + * \param object An object. + * \param peer A value to store in the peer field. + * + * \return Returns an error if 'object' is a subtype of Null, num, or + * bool. + */ +DART_EXPORT Dart_Handle Dart_SetPeer(Dart_Handle object, void* peer); + +/* + * ====== + * Kernel + * ====== + */ + +/** + * Experimental support for Dart to Kernel parser isolate. + * + * TODO(hausner): Document finalized interface. + * + */ + +// TODO(33433): Remove kernel service from the embedding API. + +typedef enum { + Dart_KernelCompilationStatus_Unknown = -1, + Dart_KernelCompilationStatus_Ok = 0, + Dart_KernelCompilationStatus_Error = 1, + Dart_KernelCompilationStatus_Crash = 2, + Dart_KernelCompilationStatus_MsgFailed = 3, +} Dart_KernelCompilationStatus; + +typedef struct { + Dart_KernelCompilationStatus status; + bool null_safety; + char* error; + uint8_t* kernel; + intptr_t kernel_size; +} Dart_KernelCompilationResult; + +typedef enum { + Dart_KernelCompilationVerbosityLevel_Error = 0, + Dart_KernelCompilationVerbosityLevel_Warning, + Dart_KernelCompilationVerbosityLevel_Info, + Dart_KernelCompilationVerbosityLevel_All, +} Dart_KernelCompilationVerbosityLevel; + +DART_EXPORT bool Dart_IsKernelIsolate(Dart_Isolate isolate); +DART_EXPORT bool Dart_KernelIsolateIsRunning(void); +DART_EXPORT Dart_Port Dart_KernelPort(void); + +/** + * Compiles the given `script_uri` to a kernel file. + * + * \param platform_kernel A buffer containing the kernel of the platform (e.g. + * `vm_platform_strong.dill`). The VM does not take ownership of this memory. + * + * \param platform_kernel_size The length of the platform_kernel buffer. + * + * \param snapshot_compile Set to `true` when the compilation is for a snapshot. + * This is used by the frontend to determine if compilation related information + * should be printed to console (e.g., null safety mode). + * + * \param verbosity Specifies the logging behavior of the kernel compilation + * service. + * + * \return Returns the result of the compilation. + * + * On a successful compilation the returned [Dart_KernelCompilationResult] has + * a status of [Dart_KernelCompilationStatus_Ok] and the `kernel`/`kernel_size` + * fields are set. The caller takes ownership of the malloc()ed buffer. + * + * On a failed compilation the `error` might be set describing the reason for + * the failed compilation. The caller takes ownership of the malloc()ed + * error. + * + * Requires there to be a current isolate. + */ +DART_EXPORT Dart_KernelCompilationResult +Dart_CompileToKernel(const char* script_uri, + const uint8_t* platform_kernel, + const intptr_t platform_kernel_size, + bool incremental_compile, + bool snapshot_compile, + const char* package_config, + Dart_KernelCompilationVerbosityLevel verbosity); + +typedef struct { + const char* uri; + const char* source; +} Dart_SourceFile; + +DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies(void); + +/** + * Sets the kernel buffer which will be used to load Dart SDK sources + * dynamically at runtime. + * + * \param platform_kernel A buffer containing kernel which has sources for the + * Dart SDK populated. Note: The VM does not take ownership of this memory. + * + * \param platform_kernel_size The length of the platform_kernel buffer. + */ +DART_EXPORT void Dart_SetDartLibrarySourcesKernel( + const uint8_t* platform_kernel, + const intptr_t platform_kernel_size); + +/** + * Detect the null safety opt-in status. + * + * When running from source, it is based on the opt-in status of `script_uri`. + * When running from a kernel buffer, it is based on the mode used when + * generating `kernel_buffer`. + * When running from an appJIT or AOT snapshot, it is based on the mode used + * when generating `snapshot_data`. + * + * \param script_uri Uri of the script that contains the source code + * + * \param package_config Uri of the package configuration file (either in format + * of .packages or .dart_tool/package_config.json) for the null safety + * detection to resolve package imports against. If this parameter is not + * passed the package resolution of the parent isolate should be used. + * + * \param original_working_directory current working directory when the VM + * process was launched, this is used to correctly resolve the path specified + * for package_config. + * + * \param snapshot_data Buffer containing the snapshot data of the + * isolate or NULL if no snapshot is provided. If provided, the buffers must + * remain valid until the isolate shuts down. + * + * \param snapshot_instructions Buffer containing the snapshot instructions of + * the isolate or NULL if no snapshot is provided. If provided, the buffers + * must remain valid until the isolate shuts down. + * + * \param kernel_buffer A buffer which contains a kernel/DIL program. Must + * remain valid until isolate shutdown. + * + * \param kernel_buffer_size The size of `kernel_buffer`. + * + * \return Returns true if the null safety is opted in by the input being + * run `script_uri`, `snapshot_data` or `kernel_buffer`. + * + */ +DART_EXPORT bool Dart_DetectNullSafety(const char* script_uri, + const char* package_config, + const char* original_working_directory, + const uint8_t* snapshot_data, + const uint8_t* snapshot_instructions, + const uint8_t* kernel_buffer, + intptr_t kernel_buffer_size); + +#define DART_KERNEL_ISOLATE_NAME "kernel-service" + +/* + * ======= + * Service + * ======= + */ + +#define DART_VM_SERVICE_ISOLATE_NAME "vm-service" + +/** + * Returns true if isolate is the service isolate. + * + * \param isolate An isolate + * + * \return Returns true if 'isolate' is the service isolate. + */ +DART_EXPORT bool Dart_IsServiceIsolate(Dart_Isolate isolate); + +/** + * Writes the CPU profile to the timeline as a series of 'instant' events. + * + * Note that this is an expensive operation. + * + * \param main_port The main port of the Isolate whose profile samples to write. + * \param error An optional error, must be free()ed by caller. + * + * \return Returns true if the profile is successfully written and false + * otherwise. + */ +DART_EXPORT bool Dart_WriteProfileToTimeline(Dart_Port main_port, char** error); + +/* + * ============== + * Precompilation + * ============== + */ + +/** + * Compiles all functions reachable from entry points and marks + * the isolate to disallow future compilation. + * + * Entry points should be specified using `@pragma("vm:entry-point")` + * annotation. + * + * \return An error handle if a compilation error or runtime error running const + * constructors was encountered. + */ +DART_EXPORT Dart_Handle Dart_Precompile(void); + +typedef void (*Dart_CreateLoadingUnitCallback)( + void* callback_data, + intptr_t loading_unit_id, + void** write_callback_data, + void** write_debug_callback_data); +typedef void (*Dart_StreamingWriteCallback)(void* callback_data, + const uint8_t* buffer, + intptr_t size); +typedef void (*Dart_StreamingCloseCallback)(void* callback_data); + +DART_EXPORT Dart_Handle Dart_LoadingUnitLibraryUris(intptr_t loading_unit_id); + +// On Darwin systems, 'dlsym' adds an '_' to the beginning of the symbol name. +// Use the '...CSymbol' definitions for resolving through 'dlsym'. The actual +// symbol names in the objects are given by the '...AsmSymbol' definitions. +#if defined(__APPLE__) +#define kSnapshotBuildIdCSymbol "kDartSnapshotBuildId" +#define kVmSnapshotDataCSymbol "kDartVmSnapshotData" +#define kVmSnapshotInstructionsCSymbol "kDartVmSnapshotInstructions" +#define kVmSnapshotBssCSymbol "kDartVmSnapshotBss" +#define kIsolateSnapshotDataCSymbol "kDartIsolateSnapshotData" +#define kIsolateSnapshotInstructionsCSymbol "kDartIsolateSnapshotInstructions" +#define kIsolateSnapshotBssCSymbol "kDartIsolateSnapshotBss" +#else +#define kSnapshotBuildIdCSymbol "_kDartSnapshotBuildId" +#define kVmSnapshotDataCSymbol "_kDartVmSnapshotData" +#define kVmSnapshotInstructionsCSymbol "_kDartVmSnapshotInstructions" +#define kVmSnapshotBssCSymbol "_kDartVmSnapshotBss" +#define kIsolateSnapshotDataCSymbol "_kDartIsolateSnapshotData" +#define kIsolateSnapshotInstructionsCSymbol "_kDartIsolateSnapshotInstructions" +#define kIsolateSnapshotBssCSymbol "_kDartIsolateSnapshotBss" +#endif + +#define kSnapshotBuildIdAsmSymbol "_kDartSnapshotBuildId" +#define kVmSnapshotDataAsmSymbol "_kDartVmSnapshotData" +#define kVmSnapshotInstructionsAsmSymbol "_kDartVmSnapshotInstructions" +#define kVmSnapshotBssAsmSymbol "_kDartVmSnapshotBss" +#define kIsolateSnapshotDataAsmSymbol "_kDartIsolateSnapshotData" +#define kIsolateSnapshotInstructionsAsmSymbol \ + "_kDartIsolateSnapshotInstructions" +#define kIsolateSnapshotBssAsmSymbol "_kDartIsolateSnapshotBss" + +/** + * Creates a precompiled snapshot. + * - A root library must have been loaded. + * - Dart_Precompile must have been called. + * + * Outputs an assembly file defining the symbols listed in the definitions + * above. + * + * The assembly should be compiled as a static or shared library and linked or + * loaded by the embedder. Running this snapshot requires a VM compiled with + * DART_PRECOMPILED_SNAPSHOT. The kDartVmSnapshotData and + * kDartVmSnapshotInstructions should be passed to Dart_Initialize. The + * kDartIsolateSnapshotData and kDartIsolateSnapshotInstructions should be + * passed to Dart_CreateIsolateGroup. + * + * The callback will be invoked one or more times to provide the assembly code. + * + * If stripped is true, then the assembly code will not include DWARF + * debugging sections. + * + * If debug_callback_data is provided, debug_callback_data will be used with + * the callback to provide separate debugging information. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateAppAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback, + void* callback_data, + bool stripped, + void* debug_callback_data); +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateAppAOTSnapshotAsAssemblies( + Dart_CreateLoadingUnitCallback next_callback, + void* next_callback_data, + bool stripped, + Dart_StreamingWriteCallback write_callback, + Dart_StreamingCloseCallback close_callback); + +/** + * Creates a precompiled snapshot. + * - A root library must have been loaded. + * - Dart_Precompile must have been called. + * + * Outputs an ELF shared library defining the symbols + * - _kDartVmSnapshotData + * - _kDartVmSnapshotInstructions + * - _kDartIsolateSnapshotData + * - _kDartIsolateSnapshotInstructions + * + * The shared library should be dynamically loaded by the embedder. + * Running this snapshot requires a VM compiled with DART_PRECOMPILED_SNAPSHOT. + * The kDartVmSnapshotData and kDartVmSnapshotInstructions should be passed to + * Dart_Initialize. The kDartIsolateSnapshotData and + * kDartIsolateSnapshotInstructions should be passed to Dart_CreateIsolate. + * + * The callback will be invoked one or more times to provide the binary output. + * + * If stripped is true, then the binary output will not include DWARF + * debugging sections. + * + * If debug_callback_data is provided, debug_callback_data will be used with + * the callback to provide separate debugging information. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback, + void* callback_data, + bool stripped, + void* debug_callback_data); +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateAppAOTSnapshotAsElfs(Dart_CreateLoadingUnitCallback next_callback, + void* next_callback_data, + bool stripped, + Dart_StreamingWriteCallback write_callback, + Dart_StreamingCloseCallback close_callback); + +/** + * Like Dart_CreateAppAOTSnapshotAsAssembly, but only includes + * kDartVmSnapshotData and kDartVmSnapshotInstructions. It also does + * not strip DWARF information from the generated assembly or allow for + * separate debug information. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateVMAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback, + void* callback_data); + +/** + * Sorts the class-ids in depth first traversal order of the inheritance + * tree. This is a costly operation, but it can make method dispatch + * more efficient and is done before writing snapshots. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_SortClasses(void); + +/** + * Creates a snapshot that caches compiled code and type feedback for faster + * startup and quicker warmup in a subsequent process. + * + * Outputs a snapshot in two pieces. The pieces should be passed to + * Dart_CreateIsolateGroup in a VM using the same VM snapshot pieces used in the + * current VM. The instructions piece must be loaded with read and execute + * permissions; the data piece may be loaded as read-only. + * + * - Requires the VM to have not been started with --precompilation. + * - Not supported when targeting IA32. + * - The VM writing the snapshot and the VM reading the snapshot must be the + * same version, must be built in the same DEBUG/RELEASE/PRODUCT mode, must + * be targeting the same architecture, and must both be in checked mode or + * both in unchecked mode. + * + * The buffers are scope allocated and are only valid until the next call to + * Dart_ExitScope. + * + * \return A valid handle if no error occurs during the operation. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer, + intptr_t* isolate_snapshot_data_size, + uint8_t** isolate_snapshot_instructions_buffer, + intptr_t* isolate_snapshot_instructions_size); + +/** + * Like Dart_CreateAppJITSnapshotAsBlobs, but also creates a new VM snapshot. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateCoreJITSnapshotAsBlobs( + uint8_t** vm_snapshot_data_buffer, + intptr_t* vm_snapshot_data_size, + uint8_t** vm_snapshot_instructions_buffer, + intptr_t* vm_snapshot_instructions_size, + uint8_t** isolate_snapshot_data_buffer, + intptr_t* isolate_snapshot_data_size, + uint8_t** isolate_snapshot_instructions_buffer, + intptr_t* isolate_snapshot_instructions_size); + +/** + * Get obfuscation map for precompiled code. + * + * Obfuscation map is encoded as a JSON array of pairs (original name, + * obfuscated name). + * + * \return Returns an error handler if the VM was built in a mode that does not + * support obfuscation. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_GetObfuscationMap(uint8_t** buffer, intptr_t* buffer_length); + +/** + * Returns whether the VM only supports running from precompiled snapshots and + * not from any other kind of snapshot or from source (that is, the VM was + * compiled with DART_PRECOMPILED_RUNTIME). + */ +DART_EXPORT bool Dart_IsPrecompiledRuntime(void); + +/** + * Print a native stack trace. Used for crash handling. + * + * If context is NULL, prints the current stack trace. Otherwise, context + * should be a CONTEXT* (Windows) or ucontext_t* (POSIX) from a signal handler + * running on the current thread. + */ +DART_EXPORT void Dart_DumpNativeStackTrace(void* context); + +/** + * Indicate that the process is about to abort, and the Dart VM should not + * attempt to cleanup resources. + */ +DART_EXPORT void Dart_PrepareToAbort(void); + +#endif /* INCLUDE_DART_API_H_ */ /* NOLINT */ diff --git a/src/dart/native/dart/dart_api_dl.c b/src/dart/native/dart/dart_api_dl.c new file mode 100644 index 0000000000..c4a68f4449 --- /dev/null +++ b/src/dart/native/dart/dart_api_dl.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#include "dart_api_dl.h" /* NOLINT */ +#include "dart_version.h" /* NOLINT */ +#include "internal/dart_api_dl_impl.h" /* NOLINT */ + +#include + +#define DART_API_DL_DEFINITIONS(name, R, A) name##_Type name##_DL = NULL; + +DART_API_ALL_DL_SYMBOLS(DART_API_DL_DEFINITIONS) + +#undef DART_API_DL_DEFINITIONS + +typedef void* DartApiEntry_function; + +DartApiEntry_function FindFunctionPointer(const DartApiEntry* entries, + const char* name) { + while (entries->name != NULL) { + if (strcmp(entries->name, name) == 0) return entries->function; + entries++; + } + return NULL; +} + +intptr_t Dart_InitializeApiDL(void* data) { + DartApi* dart_api_data = (DartApi*)data; + + if (dart_api_data->major != DART_API_DL_MAJOR_VERSION) { + // If the DartVM we're running on does not have the same version as this + // file was compiled against, refuse to initialize. The symbols are not + // compatible. + return -1; + } + // Minor versions are allowed to be different. + // If the DartVM has a higher minor version, it will provide more symbols + // than we initialize here. + // If the DartVM has a lower minor version, it will not provide all symbols. + // In that case, we leave the missing symbols un-initialized. Those symbols + // should not be used by the Dart and native code. The client is responsible + // for checking the minor version number himself based on which symbols it + // is using. + // (If we would error out on this case, recompiling native code against a + // newer SDK would break all uses on older SDKs, which is too strict.) + + const DartApiEntry* dart_api_function_pointers = dart_api_data->functions; + +#define DART_API_DL_INIT(name, R, A) \ + name##_DL = \ + (name##_Type)(FindFunctionPointer(dart_api_function_pointers, #name)); + DART_API_ALL_DL_SYMBOLS(DART_API_DL_INIT) +#undef DART_API_DL_INIT + + return 0; +} diff --git a/src/dart/native/dart/dart_api_dl.h b/src/dart/native/dart/dart_api_dl.h new file mode 100644 index 0000000000..804b2811cd --- /dev/null +++ b/src/dart/native/dart/dart_api_dl.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_INCLUDE_DART_API_DL_H_ +#define RUNTIME_INCLUDE_DART_API_DL_H_ + +#include "dart_api.h" /* NOLINT */ +#include "dart_native_api.h" /* NOLINT */ + +/** \mainpage Dynamically Linked Dart API + * + * This exposes a subset of symbols from dart_api.h and dart_native_api.h + * available in every Dart embedder through dynamic linking. + * + * All symbols are postfixed with _DL to indicate that they are dynamically + * linked and to prevent conflicts with the original symbol. + * + * Link `dart_api_dl.c` file into your library and invoke + * `Dart_InitializeApiDL` with `NativeApi.initializeApiDLData`. + */ + +DART_EXPORT intptr_t Dart_InitializeApiDL(void* data); + +// ============================================================================ +// IMPORTANT! Never update these signatures without properly updating +// DART_API_DL_MAJOR_VERSION and DART_API_DL_MINOR_VERSION. +// +// Verbatim copy of `dart_native_api.h` and `dart_api.h` symbol names and types +// to trigger compile-time errors if the sybols in those files are updated +// without updating these. +// +// Function return and argument types, and typedefs are carbon copied. Structs +// are typechecked nominally in C/C++, so they are not copied, instead a +// comment is added to their definition. +typedef int64_t Dart_Port_DL; + +typedef void (*Dart_NativeMessageHandler_DL)(Dart_Port_DL dest_port_id, + Dart_CObject* message); + +// dart_native_api.h symbols can be called on any thread. +#define DART_NATIVE_API_DL_SYMBOLS(F) \ + /***** dart_native_api.h *****/ \ + /* Dart_Port */ \ + F(Dart_PostCObject, bool, (Dart_Port_DL port_id, Dart_CObject * message)) \ + F(Dart_PostInteger, bool, (Dart_Port_DL port_id, int64_t message)) \ + F(Dart_NewNativePort, Dart_Port_DL, \ + (const char* name, Dart_NativeMessageHandler_DL handler, \ + bool handle_concurrently)) \ + F(Dart_CloseNativePort, bool, (Dart_Port_DL native_port_id)) + +// dart_api.h symbols can only be called on Dart threads. +#define DART_API_DL_SYMBOLS(F) \ + /***** dart_api.h *****/ \ + /* Errors */ \ + F(Dart_IsError, bool, (Dart_Handle handle)) \ + F(Dart_IsApiError, bool, (Dart_Handle handle)) \ + F(Dart_IsUnhandledExceptionError, bool, (Dart_Handle handle)) \ + F(Dart_IsCompilationError, bool, (Dart_Handle handle)) \ + F(Dart_IsFatalError, bool, (Dart_Handle handle)) \ + F(Dart_GetError, const char*, (Dart_Handle handle)) \ + F(Dart_ErrorHasException, bool, (Dart_Handle handle)) \ + F(Dart_ErrorGetException, Dart_Handle, (Dart_Handle handle)) \ + F(Dart_ErrorGetStackTrace, Dart_Handle, (Dart_Handle handle)) \ + F(Dart_NewApiError, Dart_Handle, (const char* error)) \ + F(Dart_NewCompilationError, Dart_Handle, (const char* error)) \ + F(Dart_NewUnhandledExceptionError, Dart_Handle, (Dart_Handle exception)) \ + F(Dart_PropagateError, void, (Dart_Handle handle)) \ + /* Dart_Handle, Dart_PersistentHandle, Dart_WeakPersistentHandle */ \ + F(Dart_HandleFromPersistent, Dart_Handle, (Dart_PersistentHandle object)) \ + F(Dart_HandleFromWeakPersistent, Dart_Handle, \ + (Dart_WeakPersistentHandle object)) \ + F(Dart_NewPersistentHandle, Dart_PersistentHandle, (Dart_Handle object)) \ + F(Dart_SetPersistentHandle, void, \ + (Dart_PersistentHandle obj1, Dart_Handle obj2)) \ + F(Dart_DeletePersistentHandle, void, (Dart_PersistentHandle object)) \ + F(Dart_NewWeakPersistentHandle, Dart_WeakPersistentHandle, \ + (Dart_Handle object, void* peer, intptr_t external_allocation_size, \ + Dart_HandleFinalizer callback)) \ + F(Dart_DeleteWeakPersistentHandle, void, (Dart_WeakPersistentHandle object)) \ + F(Dart_UpdateExternalSize, void, \ + (Dart_WeakPersistentHandle object, intptr_t external_allocation_size)) \ + F(Dart_NewFinalizableHandle, Dart_FinalizableHandle, \ + (Dart_Handle object, void* peer, intptr_t external_allocation_size, \ + Dart_HandleFinalizer callback)) \ + F(Dart_DeleteFinalizableHandle, void, \ + (Dart_FinalizableHandle object, Dart_Handle strong_ref_to_object)) \ + F(Dart_UpdateFinalizableExternalSize, void, \ + (Dart_FinalizableHandle object, Dart_Handle strong_ref_to_object, \ + intptr_t external_allocation_size)) \ + /* Dart_Port */ \ + F(Dart_Post, bool, (Dart_Port_DL port_id, Dart_Handle object)) \ + F(Dart_NewSendPort, Dart_Handle, (Dart_Port_DL port_id)) \ + F(Dart_SendPortGetId, Dart_Handle, \ + (Dart_Handle port, Dart_Port_DL * port_id)) \ + /* Scopes */ \ + F(Dart_EnterScope, void, (void)) \ + F(Dart_ExitScope, void, (void)) + +#define DART_API_ALL_DL_SYMBOLS(F) \ + DART_NATIVE_API_DL_SYMBOLS(F) \ + DART_API_DL_SYMBOLS(F) +// IMPORTANT! Never update these signatures without properly updating +// DART_API_DL_MAJOR_VERSION and DART_API_DL_MINOR_VERSION. +// +// End of verbatim copy. +// ============================================================================ + +// Copy of definition of DART_EXPORT without 'used' attribute. +// +// The 'used' attribute cannot be used with DART_API_ALL_DL_SYMBOLS because +// they are not function declarations, but variable declarations with a +// function pointer type. +// +// The function pointer variables are initialized with the addresses of the +// functions in the VM. If we were to use function declarations instead, we +// would need to forward the call to the VM adding indirection. +#if defined(__CYGWIN__) +#error Tool chain and platform not supported. +#elif defined(_WIN32) +#if defined(DART_SHARED_LIB) +#define DART_EXPORT_DL DART_EXTERN_C __declspec(dllexport) +#else +#define DART_EXPORT_DL DART_EXTERN_C +#endif +#else +#if __GNUC__ >= 4 +#if defined(DART_SHARED_LIB) +#define DART_EXPORT_DL DART_EXTERN_C __attribute__((visibility("default"))) +#else +#define DART_EXPORT_DL DART_EXTERN_C +#endif +#else +#error Tool chain not supported. +#endif +#endif + +#define DART_API_DL_DECLARATIONS(name, R, A) \ + typedef R(*name##_Type) A; \ + DART_EXPORT_DL name##_Type name##_DL; + +DART_API_ALL_DL_SYMBOLS(DART_API_DL_DECLARATIONS) + +#undef DART_API_DL_DECLARATIONS + +#undef DART_EXPORT_DL + +#endif /* RUNTIME_INCLUDE_DART_API_DL_H_ */ /* NOLINT */ diff --git a/src/dart/native/dart/dart_native_api.h b/src/dart/native/dart/dart_native_api.h new file mode 100644 index 0000000000..66e5f93e64 --- /dev/null +++ b/src/dart/native/dart/dart_native_api.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_INCLUDE_DART_NATIVE_API_H_ +#define RUNTIME_INCLUDE_DART_NATIVE_API_H_ + +#include "dart_api.h" /* NOLINT */ + +/* + * ========================================== + * Message sending/receiving from native code + * ========================================== + */ + +/** + * A Dart_CObject is used for representing Dart objects as native C + * data outside the Dart heap. These objects are totally detached from + * the Dart heap. Only a subset of the Dart objects have a + * representation as a Dart_CObject. + * + * The string encoding in the 'value.as_string' is UTF-8. + * + * All the different types from dart:typed_data are exposed as type + * kTypedData. The specific type from dart:typed_data is in the type + * field of the as_typed_data structure. The length in the + * as_typed_data structure is always in bytes. + * + * The data for kTypedData is copied on message send and ownership remains with + * the caller. The ownership of data for kExternalTyped is passed to the VM on + * message send and returned when the VM invokes the + * Dart_HandleFinalizer callback; a non-NULL callback must be provided. + */ +typedef enum { + Dart_CObject_kNull = 0, + Dart_CObject_kBool, + Dart_CObject_kInt32, + Dart_CObject_kInt64, + Dart_CObject_kDouble, + Dart_CObject_kString, + Dart_CObject_kArray, + Dart_CObject_kTypedData, + Dart_CObject_kExternalTypedData, + Dart_CObject_kSendPort, + Dart_CObject_kCapability, + Dart_CObject_kNativePointer, + Dart_CObject_kUnsupported, + Dart_CObject_kNumberOfTypes +} Dart_CObject_Type; + +typedef struct _Dart_CObject { + Dart_CObject_Type type; + union { + bool as_bool; + int32_t as_int32; + int64_t as_int64; + double as_double; + char* as_string; + struct { + Dart_Port id; + Dart_Port origin_id; + } as_send_port; + struct { + int64_t id; + } as_capability; + struct { + intptr_t length; + struct _Dart_CObject** values; + } as_array; + struct { + Dart_TypedData_Type type; + intptr_t length; /* in elements, not bytes */ + uint8_t* values; + } as_typed_data; + struct { + Dart_TypedData_Type type; + intptr_t length; /* in elements, not bytes */ + uint8_t* data; + void* peer; + Dart_HandleFinalizer callback; + } as_external_typed_data; + struct { + intptr_t ptr; + intptr_t size; + Dart_HandleFinalizer callback; + } as_native_pointer; + } value; +} Dart_CObject; +// This struct is versioned by DART_API_DL_MAJOR_VERSION, bump the version when +// changing this struct. + +/** + * Posts a message on some port. The message will contain the Dart_CObject + * object graph rooted in 'message'. + * + * While the message is being sent the state of the graph of Dart_CObject + * structures rooted in 'message' should not be accessed, as the message + * generation will make temporary modifications to the data. When the message + * has been sent the graph will be fully restored. + * + * If true is returned, the message was enqueued, and finalizers for external + * typed data will eventually run, even if the receiving isolate shuts down + * before processing the message. If false is returned, the message was not + * enqueued and ownership of external typed data in the message remains with the + * caller. + * + * This function may be called on any thread when the VM is running (that is, + * after Dart_Initialize has returned and before Dart_Cleanup has been called). + * + * \param port_id The destination port. + * \param message The message to send. + * + * \return True if the message was posted. + */ +DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject* message); + +/** + * Posts a message on some port. The message will contain the integer 'message'. + * + * \param port_id The destination port. + * \param message The message to send. + * + * \return True if the message was posted. + */ +DART_EXPORT bool Dart_PostInteger(Dart_Port port_id, int64_t message); + +/** + * A native message handler. + * + * This handler is associated with a native port by calling + * Dart_NewNativePort. + * + * The message received is decoded into the message structure. The + * lifetime of the message data is controlled by the caller. All the + * data references from the message are allocated by the caller and + * will be reclaimed when returning to it. + */ +typedef void (*Dart_NativeMessageHandler)(Dart_Port dest_port_id, + Dart_CObject* message); + +/** + * Creates a new native port. When messages are received on this + * native port, then they will be dispatched to the provided native + * message handler. + * + * \param name The name of this port in debugging messages. + * \param handler The C handler to run when messages arrive on the port. + * \param handle_concurrently Is it okay to process requests on this + * native port concurrently? + * + * \return If successful, returns the port id for the native port. In + * case of error, returns ILLEGAL_PORT. + */ +DART_EXPORT Dart_Port Dart_NewNativePort(const char* name, + Dart_NativeMessageHandler handler, + bool handle_concurrently); +/* TODO(turnidge): Currently handle_concurrently is ignored. */ + +/** + * Closes the native port with the given id. + * + * The port must have been allocated by a call to Dart_NewNativePort. + * + * \param native_port_id The id of the native port to close. + * + * \return Returns true if the port was closed successfully. + */ +DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id); + +/* + * ================== + * Verification Tools + * ================== + */ + +/** + * Forces all loaded classes and functions to be compiled eagerly in + * the current isolate.. + * + * TODO(turnidge): Document. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_CompileAll(void); + +/** + * Finalizes all classes. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_FinalizeAllClasses(void); + +/* This function is intentionally undocumented. + * + * It should not be used outside internal tests. + */ +DART_EXPORT void* Dart_ExecuteInternalCommand(const char* command, void* arg); + +#endif /* INCLUDE_DART_NATIVE_API_H_ */ /* NOLINT */ diff --git a/src/dart/native/dart/dart_tools_api.h b/src/dart/native/dart/dart_tools_api.h new file mode 100644 index 0000000000..1a2d9bb94f --- /dev/null +++ b/src/dart/native/dart/dart_tools_api.h @@ -0,0 +1,538 @@ +// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef RUNTIME_INCLUDE_DART_TOOLS_API_H_ +#define RUNTIME_INCLUDE_DART_TOOLS_API_H_ + +#include "dart_api.h" /* NOLINT */ + +/** \mainpage Dart Tools Embedding API Reference + * + * This reference describes the Dart embedding API for tools. Tools include + * a debugger, service protocol, and timeline. + * + * NOTE: The APIs described in this file are unstable and subject to change. + * + * This reference is generated from the header include/dart_tools_api.h. + */ + +/* + * ======== + * Debugger + * ======== + */ + +/** + * ILLEGAL_ISOLATE_ID is a number guaranteed never to be associated with a + * valid isolate. + */ +#define ILLEGAL_ISOLATE_ID ILLEGAL_PORT + + +/* + * ======= + * Service + * ======= + */ + +/** + * A service request callback function. + * + * These callbacks, registered by the embedder, are called when the VM receives + * a service request it can't handle and the service request command name + * matches one of the embedder registered handlers. + * + * The return value of the callback indicates whether the response + * should be used as a regular result or an error result. + * Specifically, if the callback returns true, a regular JSON-RPC + * response is built in the following way: + * + * { + * "jsonrpc": "2.0", + * "result": , + * "id": , + * } + * + * If the callback returns false, a JSON-RPC error is built like this: + * + * { + * "jsonrpc": "2.0", + * "error": , + * "id": , + * } + * + * \param method The rpc method name. + * \param param_keys Service requests can have key-value pair parameters. The + * keys and values are flattened and stored in arrays. + * \param param_values The values associated with the keys. + * \param num_params The length of the param_keys and param_values arrays. + * \param user_data The user_data pointer registered with this handler. + * \param result A C string containing a valid JSON object. The returned + * pointer will be freed by the VM by calling free. + * + * \return True if the result is a regular JSON-RPC response, false if the + * result is a JSON-RPC error. + */ +typedef bool (*Dart_ServiceRequestCallback)(const char* method, + const char** param_keys, + const char** param_values, + intptr_t num_params, + void* user_data, + const char** json_object); + +/** + * Register a Dart_ServiceRequestCallback to be called to handle + * requests for the named rpc on a specific isolate. The callback will + * be invoked with the current isolate set to the request target. + * + * \param method The name of the method that this callback is responsible for. + * \param callback The callback to invoke. + * \param user_data The user data passed to the callback. + * + * NOTE: If multiple callbacks with the same name are registered, only + * the last callback registered will be remembered. + */ +DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback( + const char* method, + Dart_ServiceRequestCallback callback, + void* user_data); + +/** + * Register a Dart_ServiceRequestCallback to be called to handle + * requests for the named rpc. The callback will be invoked without a + * current isolate. + * + * \param method The name of the command that this callback is responsible for. + * \param callback The callback to invoke. + * \param user_data The user data passed to the callback. + * + * NOTE: If multiple callbacks with the same name are registered, only + * the last callback registered will be remembered. + */ +DART_EXPORT void Dart_RegisterRootServiceRequestCallback( + const char* method, + Dart_ServiceRequestCallback callback, + void* user_data); + +/** + * Embedder information which can be requested by the VM for internal or + * reporting purposes. + * + * The pointers in this structure are not going to be cached or freed by the VM. + */ + + #define DART_EMBEDDER_INFORMATION_CURRENT_VERSION (0x00000001) + +typedef struct { + int32_t version; + const char* name; // [optional] The name of the embedder + int64_t current_rss; // [optional] the current RSS of the embedder + int64_t max_rss; // [optional] the maximum RSS of the embedder +} Dart_EmbedderInformation; + +/** + * Callback provided by the embedder that is used by the vm to request + * information. + * + * \return Returns a pointer to a Dart_EmbedderInformation structure. + * The embedder keeps the ownership of the structure and any field in it. + * The embedder must ensure that the structure will remain valid until the + * next invokation of the callback. + */ +typedef void (*Dart_EmbedderInformationCallback)( + Dart_EmbedderInformation* info); + +/** + * Register a Dart_ServiceRequestCallback to be called to handle + * requests for the named rpc. The callback will be invoked without a + * current isolate. + * + * \param method The name of the command that this callback is responsible for. + * \param callback The callback to invoke. + * \param user_data The user data passed to the callback. + * + * NOTE: If multiple callbacks with the same name are registered, only + * the last callback registered will be remembered. + */ +DART_EXPORT void Dart_SetEmbedderInformationCallback( + Dart_EmbedderInformationCallback callback); + +/** + * Invoke a vm-service method and wait for its result. + * + * \param request_json The utf8-encoded json-rpc request. + * \param request_json_length The length of the json-rpc request. + * + * \param response_json The returned utf8-encoded json response, must be + * free()ed by caller. + * \param response_json_length The length of the returned json response. + * \param error An optional error, must be free()ed by caller. + * + * \return Whether the call was sucessfully performed. + * + * NOTE: This method does not need a current isolate and must not have the + * vm-isolate being the current isolate. It must be called after + * Dart_Initialize() and before Dart_Cleanup(). + */ +DART_EXPORT bool Dart_InvokeVMServiceMethod(uint8_t* request_json, + intptr_t request_json_length, + uint8_t** response_json, + intptr_t* response_json_length, + char** error); + +/* + * ======== + * Event Streams + * ======== + */ + +/** + * A callback invoked when the VM service gets a request to listen to + * some stream. + * + * \return Returns true iff the embedder supports the named stream id. + */ +typedef bool (*Dart_ServiceStreamListenCallback)(const char* stream_id); + +/** + * A callback invoked when the VM service gets a request to cancel + * some stream. + */ +typedef void (*Dart_ServiceStreamCancelCallback)(const char* stream_id); + +/** + * Adds VM service stream callbacks. + * + * \param listen_callback A function pointer to a listen callback function. + * A listen callback function should not be already set when this function + * is called. A NULL value removes the existing listen callback function + * if any. + * + * \param cancel_callback A function pointer to a cancel callback function. + * A cancel callback function should not be already set when this function + * is called. A NULL value removes the existing cancel callback function + * if any. + * + * \return Success if the callbacks were added. Otherwise, returns an + * error handle. + */ +DART_EXPORT char* Dart_SetServiceStreamCallbacks( + Dart_ServiceStreamListenCallback listen_callback, + Dart_ServiceStreamCancelCallback cancel_callback); + +/** + * Sends a data event to clients of the VM Service. + * + * A data event is used to pass an array of bytes to subscribed VM + * Service clients. For example, in the standalone embedder, this is + * function used to provide WriteEvents on the Stdout and Stderr + * streams. + * + * If the embedder passes in a stream id for which no client is + * subscribed, then the event is ignored. + * + * \param stream_id The id of the stream on which to post the event. + * + * \param event_kind A string identifying what kind of event this is. + * For example, 'WriteEvent'. + * + * \param bytes A pointer to an array of bytes. + * + * \param bytes_length The length of the byte array. + * + * \return NULL if the arguments are well formed. Otherwise, returns an + * error string. The caller is responsible for freeing the error message. + */ +DART_EXPORT char* Dart_ServiceSendDataEvent(const char* stream_id, + const char* event_kind, + const uint8_t* bytes, + intptr_t bytes_length); + +/** + * Usage statistics for a space/generation at a particular moment in time. + * + * \param used Amount of memory used, in bytes. + * + * \param capacity Memory capacity, in bytes. + * + * \param external External memory, in bytes. + * + * \param collections How many times the garbage collector has run in this + * space. + * + * \param time Cumulative time spent collecting garbage in this space, in + * seconds. + * + * \param avg_collection_period Average time between garbage collector running + * in this space, in milliseconds. + */ +typedef struct { + intptr_t used; + intptr_t capacity; + intptr_t external; + intptr_t collections; + double time; + double avg_collection_period; +} Dart_GCStats; + +/** + * A Garbage Collection event with memory usage statistics. + * + * \param type The event type. Static lifetime. + * + * \param reason The reason for the GC event. Static lifetime. + * + * \param new_space Data for New Space. + * + * \param old_space Data for Old Space. + */ +typedef struct { + const char* type; + const char* reason; + const char* isolate_id; + + Dart_GCStats new_space; + Dart_GCStats old_space; +} Dart_GCEvent; + +/** + * A callback invoked when the VM emits a GC event. + * + * \param event The GC event data. Pointer only valid for the duration of the + * callback. + */ +typedef void (*Dart_GCEventCallback)(Dart_GCEvent* event); + +/** + * Sets the native GC event callback. + * + * \param callback A function pointer to an event handler callback function. + * A NULL value removes the existing listen callback function if any. + */ +DART_EXPORT void Dart_SetGCEventCallback(Dart_GCEventCallback callback); + +/* + * ======== + * Reload support + * ======== + * + * These functions are used to implement reloading in the Dart VM. + * This is an experimental feature, so embedders should be prepared + * for these functions to change. + */ + +/** + * A callback which determines whether the file at some url has been + * modified since some time. If the file cannot be found, true should + * be returned. + */ +typedef bool (*Dart_FileModifiedCallback)(const char* url, int64_t since); + +DART_EXPORT char* Dart_SetFileModifiedCallback( + Dart_FileModifiedCallback file_modified_callback); + +/** + * Returns true if isolate is currently reloading. + */ +DART_EXPORT bool Dart_IsReloading(); + +/* + * ======== + * Timeline + * ======== + */ + +/** + * Enable tracking of specified timeline category. This is operational + * only when systrace timeline functionality is turned on. + * + * \param categories A comma seperated list of categories that need to + * be enabled, the categories are + * "all" : All categories + * "API" - Execution of Dart C API functions + * "Compiler" - Execution of Dart JIT compiler + * "CompilerVerbose" - More detailed Execution of Dart JIT compiler + * "Dart" - Execution of Dart code + * "Debugger" - Execution of Dart debugger + * "Embedder" - Execution of Dart embedder code + * "GC" - Execution of Dart Garbage Collector + * "Isolate" - Dart Isolate lifecycle execution + * "VM" - Excution in Dart VM runtime code + * "" - None + * + * When "all" is specified all the categories are enabled. + * When a comma seperated list of categories is specified, the categories + * that are specified will be enabled and the rest will be disabled. + * When "" is specified all the categories are disabled. + * The category names are case sensitive. + * eg: Dart_EnableTimelineCategory("all"); + * Dart_EnableTimelineCategory("GC,API,Isolate"); + * Dart_EnableTimelineCategory("GC,Debugger,Dart"); + * + * \return True if the categories were successfully enabled, False otherwise. + */ +DART_EXPORT bool Dart_SetEnabledTimelineCategory(const char* categories); + +/** + * Returns a timestamp in microseconds. This timestamp is suitable for + * passing into the timeline system, and uses the same monotonic clock + * as dart:developer's Timeline.now. + * + * \return A timestamp that can be passed to the timeline system. + */ +DART_EXPORT int64_t Dart_TimelineGetMicros(); + +/** + * Returns a raw timestamp in from the monotonic clock. + * + * \return A raw timestamp from the monotonic clock. + */ +DART_EXPORT int64_t Dart_TimelineGetTicks(); + +/** + * Returns the frequency of the monotonic clock. + * + * \return The frequency of the monotonic clock. + */ +DART_EXPORT int64_t Dart_TimelineGetTicksFrequency(); + +typedef enum { + Dart_Timeline_Event_Begin, // Phase = 'B'. + Dart_Timeline_Event_End, // Phase = 'E'. + Dart_Timeline_Event_Instant, // Phase = 'i'. + Dart_Timeline_Event_Duration, // Phase = 'X'. + Dart_Timeline_Event_Async_Begin, // Phase = 'b'. + Dart_Timeline_Event_Async_End, // Phase = 'e'. + Dart_Timeline_Event_Async_Instant, // Phase = 'n'. + Dart_Timeline_Event_Counter, // Phase = 'C'. + Dart_Timeline_Event_Flow_Begin, // Phase = 's'. + Dart_Timeline_Event_Flow_Step, // Phase = 't'. + Dart_Timeline_Event_Flow_End, // Phase = 'f'. +} Dart_Timeline_Event_Type; + +/** + * Add a timeline event to the embedder stream. + * + * \param label The name of the event. Its lifetime must extend at least until + * Dart_Cleanup. + * \param timestamp0 The first timestamp of the event. + * \param timestamp1_or_async_id The second timestamp of the event or + * the async id. + * \param argument_count The number of argument names and values. + * \param argument_names An array of names of the arguments. The lifetime of the + * names must extend at least until Dart_Cleanup. The array may be reclaimed + * when this call returns. + * \param argument_values An array of values of the arguments. The values and + * the array may be reclaimed when this call returns. + */ +DART_EXPORT void Dart_TimelineEvent(const char* label, + int64_t timestamp0, + int64_t timestamp1_or_async_id, + Dart_Timeline_Event_Type type, + intptr_t argument_count, + const char** argument_names, + const char** argument_values); + +/** + * Associates a name with the current thread. This name will be used to name + * threads in the timeline. Can only be called after a call to Dart_Initialize. + * + * \param name The name of the thread. + */ +DART_EXPORT void Dart_SetThreadName(const char* name); + +/* + * ======= + * Metrics + * ======= + */ + +/** + * Return metrics gathered for the VM and individual isolates. + * + * NOTE: Non-heap metrics are not available in PRODUCT builds of Dart. + * Calling the non-heap metric functions on a PRODUCT build might return invalid metrics. + */ +DART_EXPORT int64_t Dart_VMIsolateCountMetric(); // Counter +DART_EXPORT int64_t Dart_VMCurrentRSSMetric(); // Byte +DART_EXPORT int64_t Dart_VMPeakRSSMetric(); // Byte +DART_EXPORT int64_t +Dart_IsolateHeapOldUsedMetric(Dart_Isolate isolate); // Byte +DART_EXPORT int64_t +Dart_IsolateHeapOldUsedMaxMetric(Dart_Isolate isolate); // Byte +DART_EXPORT int64_t +Dart_IsolateHeapOldCapacityMetric(Dart_Isolate isolate); // Byte +DART_EXPORT int64_t +Dart_IsolateHeapOldCapacityMaxMetric(Dart_Isolate isolate); // Byte +DART_EXPORT int64_t +Dart_IsolateHeapOldExternalMetric(Dart_Isolate isolate); // Byte +DART_EXPORT int64_t +Dart_IsolateHeapNewUsedMetric(Dart_Isolate isolate); // Byte +DART_EXPORT int64_t +Dart_IsolateHeapNewUsedMaxMetric(Dart_Isolate isolate); // Byte +DART_EXPORT int64_t +Dart_IsolateHeapNewCapacityMetric(Dart_Isolate isolate); // Byte +DART_EXPORT int64_t +Dart_IsolateHeapNewCapacityMaxMetric(Dart_Isolate isolate); // Byte +DART_EXPORT int64_t +Dart_IsolateHeapNewExternalMetric(Dart_Isolate isolate); // Byte +DART_EXPORT int64_t +Dart_IsolateHeapGlobalUsedMetric(Dart_Isolate isolate); // Byte +DART_EXPORT int64_t +Dart_IsolateHeapGlobalUsedMaxMetric(Dart_Isolate isolate); // Byte +DART_EXPORT int64_t +Dart_IsolateRunnableLatencyMetric(Dart_Isolate isolate); // Microsecond +DART_EXPORT int64_t +Dart_IsolateRunnableHeapSizeMetric(Dart_Isolate isolate); // Byte + +/* + * ======== + * UserTags + * ======== + */ + +/* + * Gets the current isolate's currently set UserTag instance. + * + * \return The currently set UserTag instance. + */ +DART_EXPORT Dart_Handle Dart_GetCurrentUserTag(); + +/* + * Gets the current isolate's default UserTag instance. + * + * \return The default UserTag with label 'Default' + */ +DART_EXPORT Dart_Handle Dart_GetDefaultUserTag(); + +/* + * Creates a new UserTag instance. + * + * \param label The name of the new UserTag. + * + * \return The newly created UserTag instance or an error handle. + */ +DART_EXPORT Dart_Handle Dart_NewUserTag(const char* label); + +/* + * Updates the current isolate's UserTag to a new value. + * + * \param user_tag The UserTag to be set as the current UserTag. + * + * \return The previously set UserTag instance or an error handle. + */ +DART_EXPORT Dart_Handle Dart_SetCurrentUserTag(Dart_Handle user_tag); + +/* + * Returns the label of a given UserTag instance. + * + * \param user_tag The UserTag from which the label will be retrieved. + * + * \return The UserTag's label. NULL if the user_tag is invalid. The caller is + * responsible for freeing the returned label. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_GetUserTagLabel( + Dart_Handle user_tag); + +#endif // RUNTIME_INCLUDE_DART_TOOLS_API_H_ diff --git a/src/dart/native/dart/dart_version.h b/src/dart/native/dart/dart_version.h new file mode 100644 index 0000000000..b3b4924392 --- /dev/null +++ b/src/dart/native/dart/dart_version.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_INCLUDE_DART_VERSION_H_ +#define RUNTIME_INCLUDE_DART_VERSION_H_ + +// On breaking changes the major version is increased. +// On backwards compatible changes the minor version is increased. +// The versioning covers the symbols exposed in dart_api_dl.h +#define DART_API_DL_MAJOR_VERSION 2 +#define DART_API_DL_MINOR_VERSION 0 + +#endif /* RUNTIME_INCLUDE_DART_VERSION_H_ */ /* NOLINT */ diff --git a/src/dart/native/dart/internal/dart_api_dl_impl.h b/src/dart/native/dart/internal/dart_api_dl_impl.h new file mode 100644 index 0000000000..e4a5689314 --- /dev/null +++ b/src/dart/native/dart/internal/dart_api_dl_impl.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_ +#define RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_ + +typedef struct { + const char* name; + void (*function)(void); +} DartApiEntry; + +typedef struct { + const int major; + const int minor; + const DartApiEntry* const functions; +} DartApi; + +#endif /* RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_ */ /* NOLINT */ diff --git a/src/dart/native/include/AsstDartApi.h b/src/dart/native/include/AsstDartApi.h new file mode 100644 index 0000000000..5e04e495a0 --- /dev/null +++ b/src/dart/native/include/AsstDartApi.h @@ -0,0 +1,9 @@ +#ifndef ASST_DART_API_H_ +#define ASST_DART_API_H_ +#include "dart_api.h" +#include "AsstCaller.h" + +DART_EXPORT AsstHandle AsstCreateWithDartPort(Dart_Port *dart_port); +DART_EXPORT void InitDartVM(void *data); + +#endif \ No newline at end of file diff --git a/src/dart/native/src/AsstDartApi.cpp b/src/dart/native/src/AsstDartApi.cpp new file mode 100644 index 0000000000..41d9d4d061 --- /dev/null +++ b/src/dart/native/src/AsstDartApi.cpp @@ -0,0 +1,42 @@ +#include "AsstDartApi.h" +#include "AsstCaller.h" +#include "dart_api.h" +#include "dart_api_dl.h" + +#include +#include + +DART_EXPORT AsstHandle AsstCreateWithDartPort(Dart_Port *dart_port) +{ + std::cout << "CPP: Dart_Port Pointer " << dart_port << std::endl; + std::cout << "CPP: Native Port: " << *dart_port << std::endl; + AsstApiCallback dart_cb = [](int msg, const char* detail, void* custom_arg) + { + Dart_CObject obj; + obj.type = Dart_CObject_kString; + obj.value.as_string = const_cast(detail); + Dart_Port port = *(Dart_Port *)custom_arg; + std::cout << "CPP: Native Port in closure: " << port << std::endl; + bool res = Dart_PostCObject(port, &obj); + if (!res) { + std::cerr << "CPP: Dart_PostCObject failed" << std::endl; + } else { + std::cout << "CPP: Successfully Sent message: " << detail << std::endl; + } + }; + + return AsstCreateEx(dart_cb, dart_port); +} + +DART_EXPORT void InitDartVM(void *data) +{ + std::cout << "CPP: InitDartVM" << std::endl; + Dart_InitializeParams* params = (Dart_InitializeParams*) data; + char* res = Dart_Initialize(params); + if (res) { + std::cerr << "CPP: Dart_Initialize failed:" << res << std::endl; + } else { + std::cout << "CPP: Dart_Initialize success" << std::endl; + } + free(res); +} \ No newline at end of file diff --git a/src/dart/pubspec.yaml b/src/dart/pubspec.yaml new file mode 100644 index 0000000000..a032284bf2 --- /dev/null +++ b/src/dart/pubspec.yaml @@ -0,0 +1,63 @@ +name: maa_core +description: A new flutter plugin project. +version: 0.0.1 +homepage: + +environment: + sdk: ">=2.16.2 <3.0.0" + flutter: ">=2.5.0" + +dependencies: + ffi: ^1.1.2 + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^1.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + # This section identifies this Flutter project as a plugin project. + # The 'pluginClass' and Android 'package' identifiers should not ordinarily + # be modified. They are used by the tooling to maintain consistency when + # adding or updating assets for this project. + plugin: + platforms: + linux: + pluginClass: MaaCorePlugin + + # To add assets to your plugin package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/assets-and-images/#from-packages + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # To add custom fonts to your plugin package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/custom-fonts/#from-packages From eaa2981aa74f70c5f7acbc898d24503c65d35a2b Mon Sep 17 00:00:00 2001 From: zzyyyl <74587068+zzyyyl@users.noreply.github.com> Date: Fri, 13 May 2022 17:07:31 +0800 Subject: [PATCH 12/31] =?UTF-8?q?feat.=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E6=A3=80=E6=9F=A5=E6=9B=B4=E6=96=B0=E7=9A=84?= =?UTF-8?q?=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VersionUpdateSettingsUserControl.xaml | 7 ++++--- src/MeoAsstGui/ViewModels/SettingsViewModel.cs | 12 ++++++++++++ src/MeoAsstGui/ViewModels/VersionUpdateViewModel.cs | 4 ++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/MeoAsstGui/UserControl/VersionUpdateSettingsUserControl.xaml b/src/MeoAsstGui/UserControl/VersionUpdateSettingsUserControl.xaml index c409bec5d1..760152a30d 100644 --- a/src/MeoAsstGui/UserControl/VersionUpdateSettingsUserControl.xaml +++ b/src/MeoAsstGui/UserControl/VersionUpdateSettingsUserControl.xaml @@ -17,9 +17,10 @@ - - - + + + + diff --git a/src/MeoAsstGui/ViewModels/SettingsViewModel.cs b/src/MeoAsstGui/ViewModels/SettingsViewModel.cs index 09c76265e6..e85ec22487 100644 --- a/src/MeoAsstGui/ViewModels/SettingsViewModel.cs +++ b/src/MeoAsstGui/ViewModels/SettingsViewModel.cs @@ -712,6 +712,18 @@ namespace MeoAsstGui } } + private bool _updateCheck = Convert.ToBoolean(ViewStatusStorage.Get("VersionUpdate.UpdateCheck", bool.TrueString)); + + public bool UpdateCheck + { + get { return _updateCheck; } + set + { + SetAndNotify(ref _updateCheck, value); + ViewStatusStorage.Set("VersionUpdate.UpdateCheck", value.ToString()); + } + } + private string _proxy = ViewStatusStorage.Get("VersionUpdate.Proxy", string.Empty); public string Proxy diff --git a/src/MeoAsstGui/ViewModels/VersionUpdateViewModel.cs b/src/MeoAsstGui/ViewModels/VersionUpdateViewModel.cs index c4ffdd5cc5..d68db88a7a 100644 --- a/src/MeoAsstGui/ViewModels/VersionUpdateViewModel.cs +++ b/src/MeoAsstGui/ViewModels/VersionUpdateViewModel.cs @@ -307,6 +307,10 @@ namespace MeoAsstGui public bool CheckUpdate() { var settings = _container.Get(); + if (!settings.UpdateCheck) + { + return false; + } const int requestRetryMaxTimes = 5; var response = RequestApi(RequestUrl); for (int i = 0; response.Length == 0 && i >= requestRetryMaxTimes; i++) From 7766dabf8c968e8003970d1af2936a9e346c9422 Mon Sep 17 00:00:00 2001 From: zzyyyl <74587068+zzyyyl@users.noreply.github.com> Date: Fri, 13 May 2022 17:08:09 +0800 Subject: [PATCH 13/31] =?UTF-8?q?perf.=E7=94=A8=E5=85=A8=E8=A7=92=E7=A9=BA?= =?UTF-8?q?=E6=A0=BC=E5=AF=B9=E9=BD=90`=E5=90=83=E7=9F=B3=E5=A4=B4`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 强迫症狂喜 --- src/MeoAsstGui/UserControl/FightSettingsUserControl.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MeoAsstGui/UserControl/FightSettingsUserControl.xaml b/src/MeoAsstGui/UserControl/FightSettingsUserControl.xaml index b639be1276..0d39d07b11 100644 --- a/src/MeoAsstGui/UserControl/FightSettingsUserControl.xaml +++ b/src/MeoAsstGui/UserControl/FightSettingsUserControl.xaml @@ -24,7 +24,7 @@ - + From 7eab0f15e55d58c5d128a54a13a6798ca87b936a Mon Sep 17 00:00:00 2001 From: zzyyyl <74587068+zzyyyl@users.noreply.github.com> Date: Fri, 13 May 2022 17:28:00 +0800 Subject: [PATCH 14/31] =?UTF-8?q?fix.=E4=BF=AE=E5=A4=8D=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=89=88=E6=9C=AC=E6=97=B6=E4=B8=8D=E4=BC=9A?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E6=AD=A3=E5=BC=8F=E7=89=88=E6=9C=AC=E7=9A=84?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 怎么还有for越界的问题(? --- src/MeoAsstGui/ViewModels/VersionUpdateViewModel.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/MeoAsstGui/ViewModels/VersionUpdateViewModel.cs b/src/MeoAsstGui/ViewModels/VersionUpdateViewModel.cs index d68db88a7a..9623b31b68 100644 --- a/src/MeoAsstGui/ViewModels/VersionUpdateViewModel.cs +++ b/src/MeoAsstGui/ViewModels/VersionUpdateViewModel.cs @@ -326,14 +326,17 @@ namespace MeoAsstGui { var releaseArray = JsonConvert.DeserializeObject(response) as JArray; - for (int i = 0; i <= releaseArray.Count; i++) + for (int i = 0; i < releaseArray.Count; i++) { - if (((bool)releaseArray[i]["prerelease"]) && settings.UpdateBeta) + if ((bool)releaseArray[i]["prerelease"]) { - _lastestJson = releaseArray[i] as JObject; - break; + if (settings.UpdateBeta) + { + _lastestJson = releaseArray[i] as JObject; + break; + } } - else if ((!(bool)releaseArray[i]["prerelease"]) && (!settings.UpdateBeta)) + else { _lastestJson = releaseArray[i] as JObject; break; From f2864546d7934c1f41e6025b4e7c54a9930ed920 Mon Sep 17 00:00:00 2001 From: Alex Zhang Date: Fri, 13 May 2022 21:49:46 +0800 Subject: [PATCH 15/31] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=86dartapi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dart/example/.gitignore | 1 + src/dart/example/lib/main.dart | 28 +++-- src/dart/lib/maa_core.dart | 119 ++++++++++-------- src/dart/lib/typedefs.dart | 15 ++- src/dart/native/CMakeLists.txt | 30 +---- src/dart/native/callback.c | 32 +++++ src/dart/native/{dart => }/dart_api_dl.c | 0 src/dart/native/include/AsstDartApi.h | 9 -- src/dart/native/{dart => include}/dart_api.h | 0 .../native/{dart => include}/dart_api_dl.h | 0 .../{dart => include}/dart_native_api.h | 0 .../native/{dart => include}/dart_tools_api.h | 0 .../native/{dart => include}/dart_version.h | 0 .../internal/dart_api_dl_impl.h | 0 src/dart/native/src/AsstDartApi.cpp | 42 ------- 15 files changed, 131 insertions(+), 145 deletions(-) create mode 100644 src/dart/native/callback.c rename src/dart/native/{dart => }/dart_api_dl.c (100%) delete mode 100644 src/dart/native/include/AsstDartApi.h rename src/dart/native/{dart => include}/dart_api.h (100%) rename src/dart/native/{dart => include}/dart_api_dl.h (100%) rename src/dart/native/{dart => include}/dart_native_api.h (100%) rename src/dart/native/{dart => include}/dart_tools_api.h (100%) rename src/dart/native/{dart => include}/dart_version.h (100%) rename src/dart/native/{dart => include}/internal/dart_api_dl_impl.h (100%) delete mode 100644 src/dart/native/src/AsstDartApi.cpp diff --git a/src/dart/example/.gitignore b/src/dart/example/.gitignore index 0fa6b675c0..e717a6f12b 100644 --- a/src/dart/example/.gitignore +++ b/src/dart/example/.gitignore @@ -14,6 +14,7 @@ *.ipr *.iws .idea/ +resource/ # The .vscode folder contains launch configuration and tasks you configure in # VS Code which you may wish to be included in version control, so this line diff --git a/src/dart/example/lib/main.dart b/src/dart/example/lib/main.dart index b95ada0972..52f2461a64 100644 --- a/src/dart/example/lib/main.dart +++ b/src/dart/example/lib/main.dart @@ -8,6 +8,7 @@ import 'package:maa_core/typedefs.dart'; import "package:path/path.dart" as p; void main() { + print(Directory.current.path); runApp(const MyApp()); } @@ -56,16 +57,18 @@ class MyHomePage extends StatefulWidget { class _MyHomePageState extends State { late MaaCore _asst; - List _logs =[]; + List _logs = []; @override void initState() { setState(() { - _asst = MaaCore(p.join(p.current, 'linux')); + _asst = MaaCore(p.current, callback); + _asst.connect('adb', 'emulator-5554'); }); super.initState(); } - void callback(dynamic message) { + + void callback(String message) { setState(() { _logs.add(message); }); @@ -81,16 +84,15 @@ class _MyHomePageState extends State { // than having to individually change instances of widgets. return Scaffold( - appBar: AppBar( - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text(widget.title), - ), - body: Center( - child: Column( - children: _logs.map((e) => Text(e)).toList(), + appBar: AppBar( + // Here we take the value from the MyHomePage object that was created by + // the App.build method, and use it to set our appbar title. + title: Text(widget.title), ), - ) - ); + body: Center( + child: Column( + children: _logs.map((e) => Text(e)).toList(), + ), + )); } } diff --git a/src/dart/lib/maa_core.dart b/src/dart/lib/maa_core.dart index ea63a26810..1db8bd8d8c 100644 --- a/src/dart/lib/maa_core.dart +++ b/src/dart/lib/maa_core.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:ffi'; import 'dart:convert'; import 'dart:isolate'; @@ -7,6 +8,9 @@ import 'package:path/path.dart' as p; class MaaCore implements MaaCoreInterface { late Assistant _asst; + late AsstLoadResourceFunc _asstLoadResource; + late AsstCreateFunc _asstCreate; + late AsstCreateExFunc _asstCreateEx; late AsstConnectFunc _asstConnect; late AsstDestroyFunc _asstDestroy; late AsstAppendTaskFunc _asstAppendTask; @@ -16,39 +20,67 @@ class MaaCore implements MaaCoreInterface { late AsstCtrlerClickFunc _asstCtrlerClick; late AsstGetVersionFunc _asstGetVersion; late AsstLogFunc _asstLog; - static bool resourceLoaded = false; + static bool _resourceLoaded = false; late ReceivePort? _receivePort; + static bool _apiInited = false; ReceivePort? get receivePort => _receivePort; - late Pointer _pointer; + late StreamSubscription _portSubscription; + late List _allocated; + static Future get platformVersion async { return Future(() => '0.0.1'); } - static bool loadResource(DynamicLibrary lib, String resourceDir) { - final AsstLoadResourceFunc asstLoadResource = - lib.lookup('AsstLoadResource').asFunction(); - if (!resourceLoaded) { - return asstLoadResource(resourceDir.toNativeUtf8()); - } - return true; + void _loadResource(String path) { + final strPtr = toManagedString(path); + final result = _asstLoadResource(strPtr); + _resourceLoaded = _resourceLoaded || result; } - MaaCore(String libDir, [Function(dynamic)? callback]) { - + MaaCore(String libDir, [Function(String)? callback]) { _loadCppLib(libDir); - final _createWithDartPort = loadAsstCreateDart(libDir); - _receivePort = ReceivePort(); - final portPtr = malloc.allocate(sizeOf()); - portPtr.value = _receivePort!.sendPort.nativePort; - _asst = _createWithDartPort(portPtr); - if (callback != null) { - _receivePort!.listen(callback); + if (!_apiInited) { + final callbackLib = DynamicLibrary.open(p.join(libDir, 'libCallback.so')); + final InitDartApiFunc initNativeApi = + callbackLib.lookup('init_dart_api').asFunction(); + initNativeApi(NativeApi.initializeApiDLData); + _apiInited = true; } + + _allocated = []; + if (!_resourceLoaded) { + _loadResource(libDir); + } + _receivePort = ReceivePort(); + final nativePort = _receivePort!.sendPort.nativePort; + final portPtr = malloc.allocate(sizeOf()); + _asst = _asstCreateEx(nativeCallback, portPtr.cast()); + _allocated.add(portPtr); + portPtr.value = nativePort; + if (callback != null) { + _portSubscription = _receivePort!.listen(_wrapCallback(callback)); + } + } + + void Function(dynamic) _wrapCallback(void Function(String) cb) { + return (dynamic data) { + // c will manage the memory for the string + String msg = data; + cb(msg); + }; + } + + Pointer get nativeCallback { + return DynamicLibrary.open('./libCallback.so') + .lookup('callback'); } void _loadCppLib(String libDir) { final lib = DynamicLibrary.open(p.join(libDir, 'libMeoAssistant.so')); - + _asstLoadResource = + lib.lookup('AsstLoadResource').asFunction(); + _asstCreate = lib.lookup('AsstCreate').asFunction(); + _asstCreateEx = lib.lookup('AsstCreateEx').asFunction(); _asstConnect = lib.lookup('AsstConnect').asFunction(); _asstDestroy = lib.lookup('AsstDestroy').asFunction(); _asstAppendTask = @@ -65,24 +97,24 @@ class MaaCore implements MaaCoreInterface { } @override - bool connect({ - required String adbPath, - required String address, - String config = '', - }) { + bool connect(adbPath, address, [config = '']) { return _asstConnect( _asst, - adbPath.toNativeUtf8(), - address.toNativeUtf8(), - config.toNativeUtf8(), + toManagedString(adbPath), + toManagedString(address), + toManagedString(config), ); } @override void destroy() { if (_receivePort != null) { + _portSubscription.cancel(); _receivePort!.close(); - malloc.free(_pointer); + } + while (_allocated.isNotEmpty) { + final ptr = _allocated.removeLast(); + malloc.free(ptr); } _asstDestroy(_asst); } @@ -92,8 +124,8 @@ class MaaCore implements MaaCoreInterface { final json = jsonEncode(params ?? {}); final taskId = _asstAppendTask( _asst, - type.toNativeUtf8(), - json.toNativeUtf8(), + toManagedString(type), + toManagedString(json), ); return taskId; } @@ -104,7 +136,7 @@ class MaaCore implements MaaCoreInterface { final result = _asstSetTaskParams( _asst, taskId, - json.toNativeUtf8(), + toManagedString(json), ); return result; } @@ -131,23 +163,12 @@ class MaaCore implements MaaCoreInterface { @override void log(String logLevel, String msg) { - _asstLog(logLevel.toNativeUtf8(), msg.toNativeUtf8()); + _asstLog(toManagedString(logLevel), toManagedString(msg)); + } + + Pointer toManagedString(String str) { + final ptr = str.toNativeUtf8(); + _allocated.add(ptr); + return ptr; } } - -AsstCreateDartFunc loadAsstCreateDart(String libPath) { - final lib = DynamicLibrary.open(p.join(libPath, 'libMeoAssistantDart.so')); - return lib - .lookup('AsstCreateWithDartPort') - .asFunction(); -} - -InitDartVMFunc loadInitDartVM(String libPath) { - final lib = DynamicLibrary.open(p.join(libPath, 'libMeoAssistantDart.so')); - return lib.lookup('InitDartVM').asFunction(); -} - -CleanUpDartVMFunc loadCleanUpDartVM(String libPath) { - final lib = DynamicLibrary.open(p.join(libPath, 'libMeoAssistantDart.so')); - return lib.lookup('CleanUpDartVM').asFunction(); -} diff --git a/src/dart/lib/typedefs.dart b/src/dart/lib/typedefs.dart index d3e6fac7d9..10f75e6930 100644 --- a/src/dart/lib/typedefs.dart +++ b/src/dart/lib/typedefs.dart @@ -3,14 +3,14 @@ import "dart:ffi"; import "package:ffi/ffi.dart"; typedef Assistant = Pointer; -typedef AsstCallbackNative - = NativeFunction)>; - -typedef AsstCallbackFunc = Void Function(Int32, StringPtr, Pointer); +typedef AsstCallbackFunc = void Function(int, Pointer, Pointer); +typedef AsstCallbackNative = NativeFunction, Pointer)>; // AsstCreateEx typedef AsstCreateDartFunc = Assistant Function(Pointer); typedef AsstCreateDartNative = NativeFunction)>; +typedef AsstCreateExFunc = Assistant Function(Pointer, Pointer); +typedef AsstCreateExNative = NativeFunction; // AsstCreate typedef AsstCreateFunc = Assistant Function(); @@ -65,8 +65,8 @@ typedef TaskId = int; typedef TaskIdNative = Int32; typedef StringPtr = Pointer; -typedef InitDartVMFunc = void Function(Pointer); -typedef InitDartVMNative = NativeFunction)>; +typedef InitDartApiFunc = void Function(Pointer); +typedef InitDartApiNative = NativeFunction)>; typedef CleanUpDartVMFunc = void Function(); @@ -74,8 +74,7 @@ typedef CleanUpDartVMNative = NativeFunction; abstract class MaaCoreInterface { void destroy(); - bool connect( - {required String adbPath, required String address, String config = ''}); + bool connect(String adbPath, String address,[String config = '']); TaskId appendTask(String type, [Map? params]); bool setTaskParams(TaskId taskId, [Map? params]); bool start(); diff --git a/src/dart/native/CMakeLists.txt b/src/dart/native/CMakeLists.txt index 0380552352..b9508118c1 100644 --- a/src/dart/native/CMakeLists.txt +++ b/src/dart/native/CMakeLists.txt @@ -1,27 +1,9 @@ cmake_minimum_required(VERSION 2.8) -project(MeoAssistantArknightsDart) +project(callback) -if (WIN32) - add_compile_options("$<$:/utf-8>") - add_compile_options("$<$:/utf-8>") - add_compile_options("$<$:/MP>") - add_compile_options("$<$:/MP>") +add_library(Callback SHARED callback.c dart_api_dl.c) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") -endif() - -add_compile_options("$<$:/W4>") -add_compile_options("$<$>:-Wall;-Wextra;-Wpedantic>") -add_library(MeoAssistantDart SHARED src/AsstDartApi.cpp) -set(CMAKE_CXX_STANDARD 17) -set(MAA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../..") - - -include_directories("include" "${MAA_ROOT}/include" "dart" "dart/internal") -find_library(MeoAssistant PATHS "${CMAKE_CURRENT_SOURCE}/lib") - - -target_link_libraries(MeoAssistantDart PUBLIC ${MeoAssitant}) -install(TARGETS MeoAssistantDart DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/../linux") -install(FILES lib/libMeoAssistant.so DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/../linux") +target_include_directories(Callback PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_SOURCE_DIR}/include/internal" +) diff --git a/src/dart/native/callback.c b/src/dart/native/callback.c new file mode 100644 index 0000000000..ab3200e358 --- /dev/null +++ b/src/dart/native/callback.c @@ -0,0 +1,32 @@ +#include "dart_api_dl.h" +#include +#include +void callback(int, const char *, void *); +void init_dart_api(void *); +void init_dart_api(void *api_data) { + Dart_InitializeApiDL(api_data); +} + +void callback(int retval, const char *json_str, void *custom_arg) { + Dart_Port port = *(Dart_Port *)custom_arg; + + + int n_digits = 1; + int k = retval; + while (k > 10) { + n_digits++; + k /= 10; + } + Dart_CObject obj; + int required_len = n_digits + strlen(json_str) + 1; + char retstr[required_len]; + retstr[required_len-1] = 0; + sprintf(retstr, "{\"retval\": %d, payload: \"%s\" }", retval, json_str); + obj.type = Dart_CObject_kString; + obj.value.as_string = retstr; + printf("C: Sending Pointer %ld to dart through port %ld\n", (int64_t)json_str, port); + char res = Dart_PostCObject_DL(port, &obj); + if (res == 0) { + printf("C: Failed to send message to Dart\n"); + } +} \ No newline at end of file diff --git a/src/dart/native/dart/dart_api_dl.c b/src/dart/native/dart_api_dl.c similarity index 100% rename from src/dart/native/dart/dart_api_dl.c rename to src/dart/native/dart_api_dl.c diff --git a/src/dart/native/include/AsstDartApi.h b/src/dart/native/include/AsstDartApi.h deleted file mode 100644 index 5e04e495a0..0000000000 --- a/src/dart/native/include/AsstDartApi.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef ASST_DART_API_H_ -#define ASST_DART_API_H_ -#include "dart_api.h" -#include "AsstCaller.h" - -DART_EXPORT AsstHandle AsstCreateWithDartPort(Dart_Port *dart_port); -DART_EXPORT void InitDartVM(void *data); - -#endif \ No newline at end of file diff --git a/src/dart/native/dart/dart_api.h b/src/dart/native/include/dart_api.h similarity index 100% rename from src/dart/native/dart/dart_api.h rename to src/dart/native/include/dart_api.h diff --git a/src/dart/native/dart/dart_api_dl.h b/src/dart/native/include/dart_api_dl.h similarity index 100% rename from src/dart/native/dart/dart_api_dl.h rename to src/dart/native/include/dart_api_dl.h diff --git a/src/dart/native/dart/dart_native_api.h b/src/dart/native/include/dart_native_api.h similarity index 100% rename from src/dart/native/dart/dart_native_api.h rename to src/dart/native/include/dart_native_api.h diff --git a/src/dart/native/dart/dart_tools_api.h b/src/dart/native/include/dart_tools_api.h similarity index 100% rename from src/dart/native/dart/dart_tools_api.h rename to src/dart/native/include/dart_tools_api.h diff --git a/src/dart/native/dart/dart_version.h b/src/dart/native/include/dart_version.h similarity index 100% rename from src/dart/native/dart/dart_version.h rename to src/dart/native/include/dart_version.h diff --git a/src/dart/native/dart/internal/dart_api_dl_impl.h b/src/dart/native/include/internal/dart_api_dl_impl.h similarity index 100% rename from src/dart/native/dart/internal/dart_api_dl_impl.h rename to src/dart/native/include/internal/dart_api_dl_impl.h diff --git a/src/dart/native/src/AsstDartApi.cpp b/src/dart/native/src/AsstDartApi.cpp deleted file mode 100644 index 41d9d4d061..0000000000 --- a/src/dart/native/src/AsstDartApi.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "AsstDartApi.h" -#include "AsstCaller.h" -#include "dart_api.h" -#include "dart_api_dl.h" - -#include -#include - -DART_EXPORT AsstHandle AsstCreateWithDartPort(Dart_Port *dart_port) -{ - std::cout << "CPP: Dart_Port Pointer " << dart_port << std::endl; - std::cout << "CPP: Native Port: " << *dart_port << std::endl; - AsstApiCallback dart_cb = [](int msg, const char* detail, void* custom_arg) - { - Dart_CObject obj; - obj.type = Dart_CObject_kString; - obj.value.as_string = const_cast(detail); - Dart_Port port = *(Dart_Port *)custom_arg; - std::cout << "CPP: Native Port in closure: " << port << std::endl; - bool res = Dart_PostCObject(port, &obj); - if (!res) { - std::cerr << "CPP: Dart_PostCObject failed" << std::endl; - } else { - std::cout << "CPP: Successfully Sent message: " << detail << std::endl; - } - }; - - return AsstCreateEx(dart_cb, dart_port); -} - -DART_EXPORT void InitDartVM(void *data) -{ - std::cout << "CPP: InitDartVM" << std::endl; - Dart_InitializeParams* params = (Dart_InitializeParams*) data; - char* res = Dart_Initialize(params); - if (res) { - std::cerr << "CPP: Dart_Initialize failed:" << res << std::endl; - } else { - std::cout << "CPP: Dart_Initialize success" << std::endl; - } - free(res); -} \ No newline at end of file From 2dbfb27cd9523c47ee2803a304075282ff883875 Mon Sep 17 00:00:00 2001 From: Alex Zhang Date: Fri, 13 May 2022 21:52:04 +0800 Subject: [PATCH 16/31] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86json=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dart/native/callback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dart/native/callback.c b/src/dart/native/callback.c index ab3200e358..ce66b0bd0f 100644 --- a/src/dart/native/callback.c +++ b/src/dart/native/callback.c @@ -21,7 +21,7 @@ void callback(int retval, const char *json_str, void *custom_arg) { int required_len = n_digits + strlen(json_str) + 1; char retstr[required_len]; retstr[required_len-1] = 0; - sprintf(retstr, "{\"retval\": %d, payload: \"%s\" }", retval, json_str); + sprintf(retstr, "{\"retval\": %d, \"payload\": %s }", retval, json_str); obj.type = Dart_CObject_kString; obj.value.as_string = retstr; printf("C: Sending Pointer %ld to dart through port %ld\n", (int64_t)json_str, port); From 0358aaaffd2c146c5304bc73759b2ca8a0d906b3 Mon Sep 17 00:00:00 2001 From: MistEO Date: Fri, 13 May 2022 21:41:39 +0800 Subject: [PATCH 17/31] =?UTF-8?q?chore.=E5=BC=BA=E5=88=B6=E6=89=93?= =?UTF-8?q?=E5=BC=80=E6=A3=80=E6=9F=A5=E6=9B=B4=E6=96=B0=E5=BC=80=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UserControl/VersionUpdateSettingsUserControl.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MeoAsstGui/UserControl/VersionUpdateSettingsUserControl.xaml b/src/MeoAsstGui/UserControl/VersionUpdateSettingsUserControl.xaml index 760152a30d..d8c616d036 100644 --- a/src/MeoAsstGui/UserControl/VersionUpdateSettingsUserControl.xaml +++ b/src/MeoAsstGui/UserControl/VersionUpdateSettingsUserControl.xaml @@ -17,7 +17,7 @@ - + From c9bd4dcb63f8c82cd175e720a9a8e2847d3925af Mon Sep 17 00:00:00 2001 From: MistEO Date: Sat, 14 May 2022 00:14:17 +0800 Subject: [PATCH 18/31] =?UTF-8?q?feat.=E6=96=B0=E5=A2=9E=E4=BF=A1=E7=94=A8?= =?UTF-8?q?=E5=95=86=E5=BA=97=E9=BB=91=E5=90=8D=E5=8D=95=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C# 一直有编码问题,交给 C++ 来转了 --- include/AsstCaller.h | 5 +++ src/MeoAssistant/AsstCaller.cpp | 22 ++++++++++++ src/MeoAsstGui/Helper/AsstProxy.cs | 20 +++++------ src/MeoAsstGui/Helper/ViewStatusStorage.cs | 9 ++--- .../UserControl/MallSettingsUserControl.xaml | 18 ++++++++-- .../ViewModels/SettingsViewModel.cs | 35 +++++++++++++++++++ .../ViewModels/TaskQueueViewModel.cs | 18 ++++++++-- 7 files changed, 105 insertions(+), 22 deletions(-) diff --git a/include/AsstCaller.h b/include/AsstCaller.h index b60172ff40..fea6d9645a 100644 --- a/include/AsstCaller.h +++ b/include/AsstCaller.h @@ -25,6 +25,11 @@ extern "C" { TaskId ASSTAPI AsstAppendTask(AsstHandle handle, const char* type, const char* params); bool ASSTAPI AsstSetTaskParams(AsstHandle handle, TaskId id, const char* params); +#ifdef _WIN32 + TaskId ASSTAPI AsstAppendTaskWithGBK(AsstHandle handle, const char* type, const char* params); + bool ASSTAPI AsstSetTaskParamsWithGBK(AsstHandle handle, TaskId id, const char* params); +#endif + bool ASSTAPI AsstStart(AsstHandle handle); bool ASSTAPI AsstStop(AsstHandle handle); diff --git a/src/MeoAssistant/AsstCaller.cpp b/src/MeoAssistant/AsstCaller.cpp index b8546e87a3..c102d5fcc7 100644 --- a/src/MeoAssistant/AsstCaller.cpp +++ b/src/MeoAssistant/AsstCaller.cpp @@ -119,6 +119,28 @@ bool AsstSetTaskParams(AsstHandle handle, TaskId id, const char* params) return handle->set_task_params(id, params); } +#ifdef _WIN32 +#include "AsstUtils.hpp" + +TaskId AsstAppendTaskWithGBK(AsstHandle handle, const char* type, const char* params) +{ + if (!inited || handle == nullptr) { + return 0; + } + + return handle->append_task(type, asst::utils::gbk_2_utf8(params)); +} + +bool AsstSetTaskParamsWithGBK(AsstHandle handle, TaskId id, const char* params) +{ + if (!inited || handle == nullptr) { + return 0; + } + + return handle->set_task_params(id, asst::utils::gbk_2_utf8(params)); +} +#endif + unsigned long long AsstGetImage(AsstHandle handle, void* buff, unsigned long long buff_size) { if (!inited || handle == nullptr || buff == nullptr) { diff --git a/src/MeoAsstGui/Helper/AsstProxy.cs b/src/MeoAsstGui/Helper/AsstProxy.cs index 9675974f97..2639a39e7c 100644 --- a/src/MeoAsstGui/Helper/AsstProxy.cs +++ b/src/MeoAsstGui/Helper/AsstProxy.cs @@ -39,9 +39,9 @@ namespace MeoAsstGui [DllImport("MeoAssistant.dll")] private static extern bool AsstConnect(AsstHandle handle, string adb_path, string address, string config); - [DllImport("MeoAssistant.dll")] private static extern TaskId AsstAppendTask(AsstHandle handle, string type, string task_params); + [DllImport("MeoAssistant.dll")] private static extern TaskId AsstAppendTaskWithGBK(AsstHandle handle, string type, string task_params); - [DllImport("MeoAssistant.dll")] private static extern bool AsstSetTaskParams(AsstHandle handle, TaskId id, string task_params); + [DllImport("MeoAssistant.dll")] private static extern bool AsstSetTaskParamsWithGBK(AsstHandle handle, TaskId id, string task_params); [DllImport("MeoAssistant.dll")] private static extern bool AsstStart(AsstHandle handle); @@ -559,7 +559,7 @@ namespace MeoAsstGui private bool AsstAppendTaskWithEncoding(string type, JObject task_params = null) { task_params = task_params ?? new JObject(); - return AsstAppendTask(_handle, type, JsonConvert.SerializeObject(task_params)) != 0; + return AsstAppendTaskWithGBK(_handle, type, JsonConvert.SerializeObject(task_params)) != 0; } public static string Utf16ToUtf8(string utf16String) @@ -601,12 +601,12 @@ namespace MeoAsstGui return AsstAppendTaskWithEncoding("Visit"); } - public bool AsstAppendMall(bool with_shopping) + public bool AsstAppendMall(bool with_shopping, bool blackMode, string[] shoppingList) { var task_params = new JObject(); task_params["shopping"] = with_shopping; - task_params["shopping_list"] = new JArray { Utf16ToUtf8("碳"), Utf16ToUtf8("家具") }; - task_params["is_black_list"] = true; + task_params["shopping_list"] = new JArray { shoppingList }; + task_params["is_black_list"] = blackMode; return AsstAppendTaskWithEncoding("Mall", task_params); } @@ -639,10 +639,10 @@ namespace MeoAsstGui var task_params = new JObject(); task_params["mode"] = mode; task_params["opers"] = new JArray { - new JObject { { "name", Utf16ToUtf8("山") }, { "skill", 2 }, { "skill_usage", 2 } }, - new JObject { { "name", Utf16ToUtf8("棘刺") }, { "skill", 3 }, { "skill_usage", 1 } }, - new JObject { { "name", Utf16ToUtf8("芙蓉") }, { "skill", 1 }, { "skill_usage", 1 } }, - new JObject { { "name", Utf16ToUtf8("梓兰") }, { "skill", 1 }, { "skill_usage", 1 } }, + new JObject { { "name", "山" }, { "skill", 2 }, { "skill_usage", 2 } }, + new JObject { { "name", "棘刺" }, { "skill", 3 }, { "skill_usage", 1 } }, + new JObject { { "name", "芙蓉" }, { "skill", 1 }, { "skill_usage", 1 } }, + new JObject { { "name", "梓兰" }, { "skill", 1 }, { "skill_usage", 1 } }, }; return AsstAppendTaskWithEncoding("Roguelike", task_params); } diff --git a/src/MeoAsstGui/Helper/ViewStatusStorage.cs b/src/MeoAsstGui/Helper/ViewStatusStorage.cs index f6749dc442..eb7ae2a96c 100644 --- a/src/MeoAsstGui/Helper/ViewStatusStorage.cs +++ b/src/MeoAsstGui/Helper/ViewStatusStorage.cs @@ -46,13 +46,10 @@ namespace MeoAsstGui { try { - using (StreamReader sr = new StreamReader(_configFilename)) - { - string jsonStr = sr.ReadToEnd(); + string jsonStr = File.ReadAllText(_configFilename); - // 文件存在但为空,会读出来一个null,感觉c#这库有bug,如果是null 就赋值一个空JObject - _viewStatus = (JObject)JsonConvert.DeserializeObject(jsonStr) ?? new JObject(); - } + // 文件存在但为空,会读出来一个null,感觉c#这库有bug,如果是null 就赋值一个空JObject + _viewStatus = (JObject)JsonConvert.DeserializeObject(jsonStr) ?? new JObject(); } catch (Exception) { diff --git a/src/MeoAsstGui/UserControl/MallSettingsUserControl.xaml b/src/MeoAsstGui/UserControl/MallSettingsUserControl.xaml index 001119dad0..10f4ee37f3 100644 --- a/src/MeoAsstGui/UserControl/MallSettingsUserControl.xaml +++ b/src/MeoAsstGui/UserControl/MallSettingsUserControl.xaml @@ -8,9 +8,21 @@ mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="550"> - - + + + + + + Content=" 信用购物 " /> + + + + + \ No newline at end of file diff --git a/src/MeoAsstGui/ViewModels/SettingsViewModel.cs b/src/MeoAsstGui/ViewModels/SettingsViewModel.cs index e85ec22487..d0835fecf9 100644 --- a/src/MeoAsstGui/ViewModels/SettingsViewModel.cs +++ b/src/MeoAsstGui/ViewModels/SettingsViewModel.cs @@ -15,6 +15,7 @@ using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Runtime.InteropServices; +using System.Text; using Notification.Wpf.Constants; using Notification.Wpf.Controls; using Stylet; @@ -338,6 +339,40 @@ namespace MeoAsstGui } } + private bool _creditBlackMode = Convert.ToBoolean(ViewStatusStorage.Get("Mall.CreditBlackMode", bool.TrueString)); + + public bool CreditBlackMode + { + get { return _creditBlackMode; } + set + { + SetAndNotify(ref _creditBlackMode, value); + ViewStatusStorage.Set("Mall.CreditBlackMode", value.ToString()); + } + } + + public static string Utf16ToUtf8(string utf16String) + { + // Get UTF16 bytes and convert UTF16 bytes to UTF8 bytes + byte[] utf16Bytes = Encoding.Unicode.GetBytes(utf16String); + byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, utf16Bytes); + + // Return UTF8 bytes as ANSI string + return Encoding.Default.GetString(utf8Bytes); + } + + private string _creditShoppingList = ViewStatusStorage.Get("Mall.CreditShoppingList", "碳 家具"); + + public string CreditShoppingList + { + get { return _creditShoppingList; } + set + { + SetAndNotify(ref _creditShoppingList, value); + ViewStatusStorage.Set("Mall.CreditShoppingList", value.ToString()); + } + } + /* 企鹅数据设置 */ private string _penguinId = ViewStatusStorage.Get("Penguin.Id", string.Empty); diff --git a/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs b/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs index 103c7c009c..ca5ef1e5b7 100644 --- a/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs +++ b/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Text; using System.Threading.Tasks; using System.Windows; using Stylet; @@ -289,13 +290,24 @@ namespace MeoAsstGui var asstProxy = _container.Get(); return asstProxy.AsstAppendInfrast(1, order.ToArray(), orderLen, settings.UsesOfDrones, settings.DormThreshold / 100.0); - } + } + + public static string Utf16ToUtf8(string utf16String) + { + // Get UTF16 bytes and convert UTF16 bytes to UTF8 bytes + byte[] utf16Bytes = Encoding.Unicode.GetBytes(utf16String); + byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, utf16Bytes); + + // Return UTF8 bytes as ANSI string + return Encoding.Default.GetString(utf8Bytes); + } private bool appendMall() { var settings = _container.Get(); - var asstProxy = _container.Get(); - return asstProxy.AsstAppendMall(settings.CreditShopping); + var asstProxy = _container.Get(); + var shopping_list = settings.CreditShoppingList.Split(' '); + return asstProxy.AsstAppendMall(settings.CreditShopping, settings.CreditBlackMode, shopping_list); } private bool appendRecruit() From dca63426a6bcfefd8bed9b294095fd41c85ddc19 Mon Sep 17 00:00:00 2001 From: MistEO Date: Sat, 14 May 2022 01:19:54 +0800 Subject: [PATCH 19/31] =?UTF-8?q?feat.=E6=96=B0=E5=A2=9E=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E4=BF=A1=E7=94=A8=E5=95=86=E5=BA=97=E4=BC=98=E5=85=88=E8=B4=AD?= =?UTF-8?q?=E4=B9=B0=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/集成文档.md | 11 ++++--- resource/tasks.json | 12 ++++--- src/MeoAssistant/CreditShopImageAnalyzer.cpp | 20 +++++++++--- src/MeoAssistant/CreditShopImageAnalyzer.h | 2 +- src/MeoAssistant/MallTask.cpp | 32 +++++++++++++------ src/MeoAssistant/MallTask.h | 1 + src/MeoAsstGui/Helper/AsstProxy.cs | 6 ++-- .../UserControl/MallSettingsUserControl.xaml | 10 +++--- .../ViewModels/SettingsViewModel.cs | 32 +++++++------------ .../ViewModels/TaskQueueViewModel.cs | 5 +-- src/Python/sample.py | 4 +-- src/Python/timed_start/timed_sample.py | 4 +-- 12 files changed, 81 insertions(+), 58 deletions(-) diff --git a/docs/集成文档.md b/docs/集成文档.md index a2d03269cf..5f847c0da9 100644 --- a/docs/集成文档.md +++ b/docs/集成文档.md @@ -97,17 +97,20 @@ TaskId ASSTAPI AsstAppendTask(AsstHandle handle, const char* type, const char* p 不支持设置参数 - `Mall` - 领取信用及商店购物 + 领取信用及商店购物。 + 会先有序的按 `buy_first` 购买一遍,再从左到右并避开 `blacklist` 购买第二遍 ```jsonc // 对应的任务参数 { "shopping": bool, // 是否购物,可选,默认 false。不支持运行中设置 - "shopping_list": [ // 购物列表,当 shopping 为 true 时必选。不支持运行中设置 + "buy_first": [ // 优先购买列表,可选。不支持运行中设置 + string, // 商品名,如 "招聘许可"、"龙门币" 等 + ], + "blacklist": [ // 黑名单列表,可选。不支持运行中设置 string, // 商品名,如 "加急许可"、"家具零件" 等 ... - ], - "is_black_list": bool // 购物列表是否是黑名单模式,可选,默认 false。不支持运行中设置 + ] } ``` diff --git a/resource/tasks.json b/resource/tasks.json index 08c2e67a2d..74271e08c8 100644 --- a/resource/tasks.json +++ b/resource/tasks.json @@ -2533,12 +2533,14 @@ 110 ] }, - "CreditShop-NotToBuy": { + "CreditShop-ProductName": { "algorithm": "OcrDetect", - "Doc": "这里的text,是子串搜索,即商品名中只要含有任一text,就不买", - "text": [ - "碳", - "家具" + "text": [], + "ocrReplace": [ + [ + "龙门.+", + "龙门币" + ] ], "roi": [ 0, diff --git a/src/MeoAssistant/CreditShopImageAnalyzer.cpp b/src/MeoAssistant/CreditShopImageAnalyzer.cpp index 4d161d5fbc..9bb93c5d83 100644 --- a/src/MeoAssistant/CreditShopImageAnalyzer.cpp +++ b/src/MeoAssistant/CreditShopImageAnalyzer.cpp @@ -59,16 +59,17 @@ bool asst::CreditShopImageAnalyzer::commoditys_analyze() bool asst::CreditShopImageAnalyzer::whether_to_buy_analyze() { - const auto not_to_buy_task_ptr = std::dynamic_pointer_cast( - Task.get("CreditShop-NotToBuy")); + const auto product_name_task_ptr = std::dynamic_pointer_cast( + Task.get("CreditShop-ProductName")); for (const Rect& commodity : m_commoditys) { // 商品名的区域 - Rect name_roi = not_to_buy_task_ptr->roi; + Rect name_roi = product_name_task_ptr->roi; name_roi.x += commodity.x; name_roi.y += commodity.y; OcrImageAnalyzer ocr_analyzer(m_image, name_roi); + ocr_analyzer.set_replace(product_name_task_ptr->replace_map); ocr_analyzer.set_required(m_shopping_list); if (ocr_analyzer.analyze()) { // 黑名单模式,有识别结果说明这个商品不买,直接跳过 @@ -84,8 +85,17 @@ bool asst::CreditShopImageAnalyzer::whether_to_buy_analyze() #ifdef ASST_DEBUG cv::rectangle(m_image_draw, utils::make_rect(commodity), cv::Scalar(0, 0, 255), 2); #endif - m_need_to_buy.emplace_back(commodity); + m_need_to_buy.emplace_back(commodity, ocr_analyzer.get_result().empty() ? std::string() : ocr_analyzer.get_result().front().text); } + + if (m_is_white_list) { + std::sort(m_need_to_buy.begin(), m_need_to_buy.end(), [&]( + const auto& lhs, const auto& rhs) -> bool { + return std::find(m_shopping_list.cbegin(), m_shopping_list.cend(), lhs.second) + < std::find(m_shopping_list.cbegin(), m_shopping_list.cend(), rhs.second); + }); + } + return !m_need_to_buy.empty(); } @@ -95,7 +105,7 @@ bool asst::CreditShopImageAnalyzer::sold_out_analyze() MatchImageAnalyzer sold_out_analyzer(m_image); sold_out_analyzer.set_task_info("CreditShop-SoldOut"); - for (const Rect& commodity : m_need_to_buy) { + for (const auto& [commodity, _] : m_need_to_buy) { sold_out_analyzer.set_roi(commodity); if (sold_out_analyzer.analyze()) { #ifdef ASST_DEBUG diff --git a/src/MeoAssistant/CreditShopImageAnalyzer.h b/src/MeoAssistant/CreditShopImageAnalyzer.h index 93e6f78f44..c18000bde7 100644 --- a/src/MeoAssistant/CreditShopImageAnalyzer.h +++ b/src/MeoAssistant/CreditShopImageAnalyzer.h @@ -34,7 +34,7 @@ namespace asst bool sold_out_analyze(); std::vector m_commoditys; - std::vector m_need_to_buy; + std::vector> m_need_to_buy; std::vector m_result; std::vector m_shopping_list; diff --git a/src/MeoAssistant/MallTask.cpp b/src/MeoAssistant/MallTask.cpp index 70b43531c6..19c9614d2d 100644 --- a/src/MeoAssistant/MallTask.cpp +++ b/src/MeoAssistant/MallTask.cpp @@ -6,12 +6,15 @@ asst::MallTask::MallTask(AsstCallback callback, void* callback_arg) : PackageTask(callback, callback_arg, TaskType), m_mall_task_ptr(std::make_shared(callback, callback_arg, TaskType)), + m_shopping_first_task_ptr(std::make_shared(callback, callback_arg, TaskType)), m_shopping_task_ptr(std::make_shared(callback, callback_arg, TaskType)) { m_mall_task_ptr->set_tasks({ "MallBegin" }); - m_shopping_task_ptr->set_enable(false); + m_shopping_first_task_ptr->set_enable(false).set_retry_times(1); + m_shopping_task_ptr->set_enable(false).set_retry_times(1); m_subtasks.emplace_back(m_mall_task_ptr); + m_subtasks.emplace_back(m_shopping_first_task_ptr); m_subtasks.emplace_back(m_shopping_task_ptr); } @@ -20,24 +23,35 @@ bool asst::MallTask::set_params(const json::value& params) bool shopping = params.get("shopping", true); if (shopping) { - if (params.contains("shopping_list") && params.at("shopping_list").is_array()) { - std::vector shopping_list; - for (auto& name : params.at("shopping_list").as_array()) { - shopping_list.emplace_back(name.as_string()); + if (params.contains("buy_first") && params.at("buy_first").is_array()) { + std::vector buy_first; + for (auto& name : params.at("buy_first").as_array()) { + buy_first.emplace_back(name.as_string()); } - if (params.get("is_black_list", false) == true) { - m_shopping_task_ptr->set_black_list(std::move(shopping_list)); + if (!buy_first.empty()) { + m_shopping_first_task_ptr->set_white_list(std::move(buy_first)); + m_shopping_first_task_ptr->set_enable(true); } else { - m_shopping_task_ptr->set_white_list(std::move(shopping_list)); + m_shopping_first_task_ptr->set_enable(false); } } else { - return false; + m_shopping_first_task_ptr->set_enable(false); } + + if (params.contains("blacklist") && params.at("blacklist").is_array()) { + std::vector shopping_list; + for (auto& name : params.at("blacklist").as_array()) { + shopping_list.emplace_back(name.as_string()); + } + m_shopping_task_ptr->set_black_list(std::move(shopping_list)); + } + m_shopping_task_ptr->set_enable(true); } else { + m_shopping_first_task_ptr->set_enable(false); m_shopping_task_ptr->set_enable(false); } return true; diff --git a/src/MeoAssistant/MallTask.h b/src/MeoAssistant/MallTask.h index 71380a716d..1d36f5f333 100644 --- a/src/MeoAssistant/MallTask.h +++ b/src/MeoAssistant/MallTask.h @@ -17,6 +17,7 @@ namespace asst static constexpr const char* TaskType = "Mall"; private: std::shared_ptr m_mall_task_ptr = nullptr; + std::shared_ptr m_shopping_first_task_ptr = nullptr; std::shared_ptr m_shopping_task_ptr = nullptr; }; } diff --git a/src/MeoAsstGui/Helper/AsstProxy.cs b/src/MeoAsstGui/Helper/AsstProxy.cs index 2639a39e7c..dc6c321355 100644 --- a/src/MeoAsstGui/Helper/AsstProxy.cs +++ b/src/MeoAsstGui/Helper/AsstProxy.cs @@ -601,12 +601,12 @@ namespace MeoAsstGui return AsstAppendTaskWithEncoding("Visit"); } - public bool AsstAppendMall(bool with_shopping, bool blackMode, string[] shoppingList) + public bool AsstAppendMall(bool with_shopping, string[] firstlist, string[] blacklist) { var task_params = new JObject(); task_params["shopping"] = with_shopping; - task_params["shopping_list"] = new JArray { shoppingList }; - task_params["is_black_list"] = blackMode; + task_params["buy_first"] = new JArray { firstlist }; + task_params["blacklist"] = new JArray { blacklist }; return AsstAppendTaskWithEncoding("Mall", task_params); } diff --git a/src/MeoAsstGui/UserControl/MallSettingsUserControl.xaml b/src/MeoAsstGui/UserControl/MallSettingsUserControl.xaml index 10f4ee37f3..d52648ce08 100644 --- a/src/MeoAsstGui/UserControl/MallSettingsUserControl.xaml +++ b/src/MeoAsstGui/UserControl/MallSettingsUserControl.xaml @@ -16,13 +16,15 @@ - + + + + - + \ No newline at end of file diff --git a/src/MeoAsstGui/ViewModels/SettingsViewModel.cs b/src/MeoAsstGui/ViewModels/SettingsViewModel.cs index d0835fecf9..20ab942de5 100644 --- a/src/MeoAsstGui/ViewModels/SettingsViewModel.cs +++ b/src/MeoAsstGui/ViewModels/SettingsViewModel.cs @@ -339,37 +339,27 @@ namespace MeoAsstGui } } - private bool _creditBlackMode = Convert.ToBoolean(ViewStatusStorage.Get("Mall.CreditBlackMode", bool.TrueString)); + private string _creditFirstList = ViewStatusStorage.Get("Mall.CreditFirstList", "招聘许可 龙门币"); - public bool CreditBlackMode + public string CreditFirstList { - get { return _creditBlackMode; } + get { return _creditFirstList; } set { - SetAndNotify(ref _creditBlackMode, value); - ViewStatusStorage.Set("Mall.CreditBlackMode", value.ToString()); + SetAndNotify(ref _creditFirstList, value); + ViewStatusStorage.Set("Mall.CreditFirstList", value.ToString()); } } - public static string Utf16ToUtf8(string utf16String) + private string _creditBlackList = ViewStatusStorage.Get("Mall.CreditBlackList", "碳 家具"); + + public string CreditBlackList { - // Get UTF16 bytes and convert UTF16 bytes to UTF8 bytes - byte[] utf16Bytes = Encoding.Unicode.GetBytes(utf16String); - byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, utf16Bytes); - - // Return UTF8 bytes as ANSI string - return Encoding.Default.GetString(utf8Bytes); - } - - private string _creditShoppingList = ViewStatusStorage.Get("Mall.CreditShoppingList", "碳 家具"); - - public string CreditShoppingList - { - get { return _creditShoppingList; } + get { return _creditBlackList; } set { - SetAndNotify(ref _creditShoppingList, value); - ViewStatusStorage.Set("Mall.CreditShoppingList", value.ToString()); + SetAndNotify(ref _creditBlackList, value); + ViewStatusStorage.Set("Mall.CreditBlackList", value.ToString()); } } diff --git a/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs b/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs index ca5ef1e5b7..fb65017a7f 100644 --- a/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs +++ b/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs @@ -306,8 +306,9 @@ namespace MeoAsstGui { var settings = _container.Get(); var asstProxy = _container.Get(); - var shopping_list = settings.CreditShoppingList.Split(' '); - return asstProxy.AsstAppendMall(settings.CreditShopping, settings.CreditBlackMode, shopping_list); + var buy_first = settings.CreditFirstList.Split(' '); + var black_list = settings.CreditBlackList.Split(' '); + return asstProxy.AsstAppendMall(settings.CreditShopping, buy_first, black_list); } private bool appendRecruit() diff --git a/src/Python/sample.py b/src/Python/sample.py index ece7a5d820..c00b38c5e6 100644 --- a/src/Python/sample.py +++ b/src/Python/sample.py @@ -52,8 +52,8 @@ if __name__ == "__main__": asst.append_task('Visit') asst.append_task('Mall', { 'shopping': True, - 'shopping_list': ['家具', '碳'], - 'is_black_list': True + 'buy_first': ['招聘许可', '龙门币'], + 'blacklist': ['家具', '碳'], }) asst.append_task('Award') # asst.append_task('Copilot', { diff --git a/src/Python/timed_start/timed_sample.py b/src/Python/timed_start/timed_sample.py index 1bd65b1fd7..090411a605 100644 --- a/src/Python/timed_start/timed_sample.py +++ b/src/Python/timed_start/timed_sample.py @@ -48,8 +48,8 @@ def job(): asst.append_task('Visit') asst.append_task('Mall', { 'shopping': True, - 'shopping_list': ['家具', '碳'], - 'is_black_list': True + 'buy_first': ['招聘许可', '龙门币'], + 'blacklist': ['家具', '碳'], }) asst.append_task('Award') From c2198344e66acbe112e7fa263426ec6749857c06 Mon Sep 17 00:00:00 2001 From: MistEO Date: Sat, 14 May 2022 01:57:03 +0800 Subject: [PATCH 20/31] chore. Treat warninngs as errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 赶尽杀绝( --- CMakeLists.txt | 8 ++++---- src/MeoAssistant/MeoAssistant.vcxproj | 5 ++++- src/MeoAsstGui/Views/RootView.xaml | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6bd6608adc..3cb40613e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 2.8) -project(MeoAssistantArknights) +cmake_minimum_required(VERSION 2.8.12) +project(MaaAssistantArknights) option(BUILD_JNI "build jni" OFF) option(BUILD_TEST "build a demo" OFF) @@ -16,8 +16,8 @@ if (WIN32) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") endif() -add_compile_options("$<$:/W4>") -add_compile_options("$<$>:-Wall;-Wextra;-Wpedantic>") +add_compile_options("$<$:/W4;/WX>") +add_compile_options("$<$>:-Wall;-Wextra;-Wpedantic;-Werror>") add_definitions(-DASST_DLL_EXPORTS) diff --git a/src/MeoAssistant/MeoAssistant.vcxproj b/src/MeoAssistant/MeoAssistant.vcxproj index 58f0172a38..1bf1ec98b3 100644 --- a/src/MeoAssistant/MeoAssistant.vcxproj +++ b/src/MeoAssistant/MeoAssistant.vcxproj @@ -249,6 +249,7 @@ MultiThreaded MaxSpeed /utf-8 /MP %(AdditionalOptions) + true Console @@ -297,6 +298,7 @@ MultiThreaded MaxSpeed /utf-8 /MP %(AdditionalOptions) + true Console @@ -327,6 +329,7 @@ true EnableFastChecks /utf-8 /MP %(AdditionalOptions) + true Console @@ -370,4 +373,4 @@ - + \ No newline at end of file diff --git a/src/MeoAsstGui/Views/RootView.xaml b/src/MeoAsstGui/Views/RootView.xaml index 93052c5a83..4e8798f2ab 100644 --- a/src/MeoAsstGui/Views/RootView.xaml +++ b/src/MeoAsstGui/Views/RootView.xaml @@ -5,7 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:s="https://github.com/canton7/Stylet" mc:Ignorable="d" - Title="MeoAssistantArknights" Height="595" Width="800"> + Title="MaaAssistantArknights" Height="595" Width="800"> From b21c15dab197dcf30dec3d8f0dc6585dbb98f999 Mon Sep 17 00:00:00 2001 From: MistEO Date: Sat, 14 May 2022 02:08:49 +0800 Subject: [PATCH 21/31] =?UTF-8?q?fix.=E4=BF=AE=E5=A4=8D`=E4=B8=8A=E6=AC=A1?= =?UTF-8?q?=E4=BD=9C=E6=88=98`=E6=98=AF`=E6=84=9A=E4=BA=BA=E5=8F=B7`?= =?UTF-8?q?=E5=85=B3=E5=8D=A1=E5=90=8E=E5=8D=A1=E4=BD=8F=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/FightTask.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/MeoAssistant/FightTask.cpp b/src/MeoAssistant/FightTask.cpp index b93d5050a3..c176ce88c4 100644 --- a/src/MeoAssistant/FightTask.cpp +++ b/src/MeoAssistant/FightTask.cpp @@ -16,6 +16,7 @@ asst::FightTask::FightTask(AsstCallback callback, void* callback_arg) .set_times_limit("StartButton2", 0) .set_times_limit("MedicineConfirm", 0) .set_times_limit("StoneConfirm", 0) + .set_times_limit("StageSNReturnFlag", 0) .set_enable(false); // 进入对应的关卡 @@ -23,6 +24,7 @@ asst::FightTask::FightTask(AsstCallback callback, void* callback_arg) .set_times_limit("StartButton2", 0) .set_times_limit("MedicineConfirm", 0) .set_times_limit("StoneConfirm", 0) + .set_times_limit("StageSNReturnFlag", 0) .set_enable(false); // 开始战斗任务 From 104646833bc5ec8caf7383f31b260ab47d3fc584 Mon Sep 17 00:00:00 2001 From: zzyyyl <74587068+zzyyyl@users.noreply.github.com> Date: Sat, 14 May 2022 02:12:03 +0800 Subject: [PATCH 22/31] =?UTF-8?q?fix.=E4=BF=AE=E5=A4=8D=E7=BC=96=E7=A0=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 中文路径也能用maa辣! windows下,路径相关的全都用gbk存储,输出到log的信息统一用utf8 --- include/AsstCaller.h | 5 --- src/MeoAssistant/AbstractConfiger.cpp | 8 ++-- src/MeoAssistant/AsstCaller.cpp | 37 +++++-------------- src/MeoAssistant/Logger.hpp | 4 ++ src/MeoAssistant/PenguinPack.cpp | 2 +- src/MeoAssistant/Resource.cpp | 8 ++-- src/MeoAsstGui/Helper/AsstProxy.cs | 37 +++++++++++-------- .../ViewModels/TaskQueueViewModel.cs | 35 ++++++------------ 8 files changed, 56 insertions(+), 80 deletions(-) diff --git a/include/AsstCaller.h b/include/AsstCaller.h index fea6d9645a..b60172ff40 100644 --- a/include/AsstCaller.h +++ b/include/AsstCaller.h @@ -25,11 +25,6 @@ extern "C" { TaskId ASSTAPI AsstAppendTask(AsstHandle handle, const char* type, const char* params); bool ASSTAPI AsstSetTaskParams(AsstHandle handle, TaskId id, const char* params); -#ifdef _WIN32 - TaskId ASSTAPI AsstAppendTaskWithGBK(AsstHandle handle, const char* type, const char* params); - bool ASSTAPI AsstSetTaskParamsWithGBK(AsstHandle handle, TaskId id, const char* params); -#endif - bool ASSTAPI AsstStart(AsstHandle handle); bool ASSTAPI AsstStop(AsstHandle handle); diff --git a/src/MeoAssistant/AbstractConfiger.cpp b/src/MeoAssistant/AbstractConfiger.cpp index fe0887b484..09bd2031e9 100644 --- a/src/MeoAssistant/AbstractConfiger.cpp +++ b/src/MeoAssistant/AbstractConfiger.cpp @@ -9,12 +9,12 @@ bool asst::AbstractConfiger::load(const std::string& filename) { LogTraceFunction; -#ifdef WIN32 - std::string cvt_filename = utils::utf8_to_gbk(filename); -#else std::string cvt_filename = filename; -#endif +#ifdef WIN32 + Log.info("Load:", utils::gbk_2_utf8(cvt_filename)); +#else Log.info("Load:", cvt_filename); +#endif if (!std::filesystem::exists(cvt_filename)) { return false; diff --git a/src/MeoAssistant/AsstCaller.cpp b/src/MeoAssistant/AsstCaller.cpp index c102d5fcc7..602cf788e0 100644 --- a/src/MeoAssistant/AsstCaller.cpp +++ b/src/MeoAssistant/AsstCaller.cpp @@ -39,8 +39,13 @@ static bool inited = false; bool AsstLoadResource(const char* path) { - bool log_inited = asst::Logger::set_dirname(std::string(path) + "/"); - bool resrc_inited = asst::Resrc.load(std::string(path) + "/resource/"); +#ifdef _WIN32 + std::string working_path = asst::utils::utf8_to_gbk(path); +#else + std::string working_path = std::string(path); +#endif + bool log_inited = asst::Logger::set_dirname(working_path + "/"); + bool resrc_inited = asst::Resrc.load(working_path + "/resource/"); if (!resrc_inited) { std::cerr << asst::Resrc.get_last_error() << std::endl; } @@ -80,7 +85,7 @@ bool AsstConnect(AsstHandle handle, const char* adb_path, const char* address, c return false; } - return handle->connect(adb_path, address, config ? config : std::string()); + return handle->connect(asst::utils::utf8_to_gbk(adb_path), address, config ? config : std::string()); } bool AsstStart(AsstHandle handle) @@ -108,38 +113,16 @@ TaskId AsstAppendTask(AsstHandle handle, const char* type, const char* params) } return handle->append_task(type, params); -} - -bool AsstSetTaskParams(AsstHandle handle, TaskId id, const char* params) -{ - if (!inited || handle == nullptr) { - return 0; - } - - return handle->set_task_params(id, params); } -#ifdef _WIN32 -#include "AsstUtils.hpp" - -TaskId AsstAppendTaskWithGBK(AsstHandle handle, const char* type, const char* params) +bool AsstSetTaskParams(AsstHandle handle, TaskId id, const char* params) { if (!inited || handle == nullptr) { return 0; } - return handle->append_task(type, asst::utils::gbk_2_utf8(params)); -} - -bool AsstSetTaskParamsWithGBK(AsstHandle handle, TaskId id, const char* params) -{ - if (!inited || handle == nullptr) { - return 0; - } - - return handle->set_task_params(id, asst::utils::gbk_2_utf8(params)); + return handle->set_task_params(id, params); } -#endif unsigned long long AsstGetImage(AsstHandle handle, void* buff, unsigned long long buff_size) { diff --git a/src/MeoAssistant/Logger.hpp b/src/MeoAssistant/Logger.hpp index 4b78d0d2f7..b2c2f47de6 100644 --- a/src/MeoAssistant/Logger.hpp +++ b/src/MeoAssistant/Logger.hpp @@ -110,7 +110,11 @@ namespace asst trace("MeoAssistant Process Start"); trace("Version", asst::Version); trace("Build DataTime", __DATE__, __TIME__); +#ifdef _WIN32 // 输出到日志的时候统一编码utf8 + trace("Working Path", asst::utils::gbk_2_utf8(m_dirname)); +#else trace("Working Path", m_dirname); +#endif trace("-----------------------------"); } diff --git a/src/MeoAssistant/PenguinPack.cpp b/src/MeoAssistant/PenguinPack.cpp index de15e91626..bb7d3e7612 100644 --- a/src/MeoAssistant/PenguinPack.cpp +++ b/src/MeoAssistant/PenguinPack.cpp @@ -20,7 +20,7 @@ bool asst::PenguinPack::load(const std::string& dir) bool ret = load_json(dir + "/json/stages.json", dir + "/json/hash_index.json"); for (const auto& file : std::filesystem::directory_iterator(dir + "/items")) { - ret &= load_templ(file.path().stem().u8string(), file.path().u8string()); + ret &= load_templ(file.path().stem().string(), file.path().string()); } return ret; } diff --git a/src/MeoAssistant/Resource.cpp b/src/MeoAssistant/Resource.cpp index 7bec4e1df8..0bcc66c1a7 100644 --- a/src/MeoAssistant/Resource.cpp +++ b/src/MeoAssistant/Resource.cpp @@ -83,8 +83,8 @@ bool asst::Resource::load(const std::string& dir) if (entry.path().extension() != ".json") { continue; } - if (!m_copilot_cfg_unique_ins.load(entry.path().u8string())) { - m_last_error = entry.path().u8string() + " Load failed"; + if (!m_copilot_cfg_unique_ins.load(entry.path().string())) { + m_last_error = entry.path().string() + " Load failed"; return false; } } @@ -93,8 +93,8 @@ bool asst::Resource::load(const std::string& dir) if (entry.path().extension() != ".json") { continue; } - if (!m_roguelike_cfg_unique_ins.load(entry.path().u8string())) { - m_last_error = entry.path().u8string() + " Load failed"; + if (!m_roguelike_cfg_unique_ins.load(entry.path().string())) { + m_last_error = entry.path().string() + " Load failed"; return false; } } diff --git a/src/MeoAsstGui/Helper/AsstProxy.cs b/src/MeoAsstGui/Helper/AsstProxy.cs index dc6c321355..35101bf9ad 100644 --- a/src/MeoAsstGui/Helper/AsstProxy.cs +++ b/src/MeoAsstGui/Helper/AsstProxy.cs @@ -29,7 +29,12 @@ namespace MeoAsstGui private delegate void ProcCallbckMsg(AsstMsg msg, JObject details); - [DllImport("MeoAssistant.dll")] private static extern bool AsstLoadResource(string dirname); + [DllImport("MeoAssistant.dll")] private static extern bool AsstLoadResource(byte[] dirname); + + private static bool AsstLoadResource(string dirname) + { + return AsstLoadResource(Encoding.UTF8.GetBytes(dirname)); + } [DllImport("MeoAssistant.dll")] private static extern AsstHandle AsstCreate(); @@ -37,17 +42,27 @@ namespace MeoAsstGui [DllImport("MeoAssistant.dll")] private static extern void AsstDestroy(AsstHandle handle); - [DllImport("MeoAssistant.dll")] private static extern bool AsstConnect(AsstHandle handle, string adb_path, string address, string config); + [DllImport("MeoAssistant.dll")] private static extern bool AsstConnect(AsstHandle handle, byte[] adb_path, byte[] address, byte[] config); - [DllImport("MeoAssistant.dll")] private static extern TaskId AsstAppendTaskWithGBK(AsstHandle handle, string type, string task_params); + private static bool AsstConnect(AsstHandle handle, string adb_path, string address, string config) + { + return AsstConnect(handle, Encoding.UTF8.GetBytes(adb_path), Encoding.UTF8.GetBytes(address), Encoding.UTF8.GetBytes(config)); + } - [DllImport("MeoAssistant.dll")] private static extern bool AsstSetTaskParamsWithGBK(AsstHandle handle, TaskId id, string task_params); + [DllImport("MeoAssistant.dll")] private static extern TaskId AsstAppendTask(AsstHandle handle, byte[] type, byte[] task_params); + + private static TaskId AsstAppendTask(AsstHandle handle, string type, string task_params) + { + return AsstAppendTask(handle, Encoding.UTF8.GetBytes(type), Encoding.UTF8.GetBytes(task_params)); + } + + [DllImport("MeoAssistant.dll")] private static extern bool AsstSetTaskParams(AsstHandle handle, TaskId id, byte[] task_params); [DllImport("MeoAssistant.dll")] private static extern bool AsstStart(AsstHandle handle); [DllImport("MeoAssistant.dll")] private static extern bool AsstStop(AsstHandle handle); - [DllImport("MeoAssistant.dll")] private static extern void AsstLog(string level, string message); + [DllImport("MeoAssistant.dll")] private static extern void AsstLog(byte[] level, byte[] message); private readonly CallbackDelegate _callback; @@ -559,17 +574,7 @@ namespace MeoAsstGui private bool AsstAppendTaskWithEncoding(string type, JObject task_params = null) { task_params = task_params ?? new JObject(); - return AsstAppendTaskWithGBK(_handle, type, JsonConvert.SerializeObject(task_params)) != 0; - } - - public static string Utf16ToUtf8(string utf16String) - { - // Get UTF16 bytes and convert UTF16 bytes to UTF8 bytes - byte[] utf16Bytes = Encoding.Unicode.GetBytes(utf16String); - byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, utf16Bytes); - - // Return UTF8 bytes as ANSI string - return Encoding.Default.GetString(utf8Bytes); + return AsstAppendTask(_handle, type, JsonConvert.SerializeObject(task_params)) != 0; } public bool AsstAppendFight(string stage, int max_medicine, int max_stone, int max_times) diff --git a/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs b/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs index fb65017a7f..1a0cb763d0 100644 --- a/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs +++ b/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs @@ -12,7 +12,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Text; using System.Threading.Tasks; using System.Windows; using Stylet; @@ -71,20 +70,20 @@ namespace MeoAsstGui new CombData { Display = "当前关卡", Value = string.Empty }, new CombData { Display = "上次作战", Value = "LastBattle" }, new CombData { Display = "剿灭作战", Value = "Annihilation" }, - new CombData { Display = "龙门币-6/5", Value = "CE-6" }, + new CombData { Display = "龙门币-6/5", Value = "CE-6" }, new CombData { Display = "经验-6/5", Value = "LS-6" }, new CombData { Display = "红票-5", Value = "AP-5" }, new CombData { Display = "技能-5", Value = "CA-5" }, - new CombData { Display = "1-7", Value = "1-7" }, - - // “愚人号” 活动关卡 - new CombData { Display = "SN-8", Value = "SN-8" }, - new CombData { Display = "SN-9", Value = "SN-9" }, - new CombData { Display = "SN-10", Value = "SN-10" }, - + new CombData { Display = "1-7", Value = "1-7" }, + + // “愚人号” 活动关卡 + new CombData { Display = "SN-8", Value = "SN-8" }, + new CombData { Display = "SN-9", Value = "SN-9" }, + new CombData { Display = "SN-10", Value = "SN-10" }, + //// “风雪过境” 活动关卡 - //new CombData { Display = "BI-7", Value = "BI-7" }, - //new CombData { Display = "BI-8", Value = "BI-8" } + //new CombData { Display = "BI-7", Value = "BI-7" }, + //new CombData { Display = "BI-8", Value = "BI-8" } }; var now = DateTime.Now; @@ -290,17 +289,7 @@ namespace MeoAsstGui var asstProxy = _container.Get(); return asstProxy.AsstAppendInfrast(1, order.ToArray(), orderLen, settings.UsesOfDrones, settings.DormThreshold / 100.0); - } - - public static string Utf16ToUtf8(string utf16String) - { - // Get UTF16 bytes and convert UTF16 bytes to UTF8 bytes - byte[] utf16Bytes = Encoding.Unicode.GetBytes(utf16String); - byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, utf16Bytes); - - // Return UTF8 bytes as ANSI string - return Encoding.Default.GetString(utf8Bytes); - } + } private bool appendMall() { @@ -481,4 +470,4 @@ namespace MeoAsstGui } } } -} +} From 88f0d2546e163d88d598e64ce5a5d99a212ff304 Mon Sep 17 00:00:00 2001 From: MistEO Date: Sat, 14 May 2022 02:45:33 +0800 Subject: [PATCH 23/31] =?UTF-8?q?fix.=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=89=8D=E4=B8=80=E4=B8=AA=E4=BB=BB=E5=8A=A1=E5=87=BA=E9=94=99?= =?UTF-8?q?=EF=BC=8C=E5=90=8E=E9=9D=A2=E7=9A=84=E4=BB=BB=E5=8A=A1=E4=B8=8D?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/AbstractTask.cpp | 6 ++++ src/MeoAssistant/AbstractTask.h | 3 ++ src/MeoAssistant/CopilotTask.cpp | 46 +++++++++++++++---------------- src/MeoAssistant/FightTask.cpp | 6 ++-- src/MeoAssistant/PackageTask.cpp | 2 +- 5 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/MeoAssistant/AbstractTask.cpp b/src/MeoAssistant/AbstractTask.cpp index 0ab5fc2cba..fb34ecd1c0 100644 --- a/src/MeoAssistant/AbstractTask.cpp +++ b/src/MeoAssistant/AbstractTask.cpp @@ -80,6 +80,12 @@ AbstractTask& asst::AbstractTask::set_enable(bool enable) noexcept return *this; } +AbstractTask& asst::AbstractTask::set_ignore_error(bool ignore) noexcept +{ + m_ignore_error = ignore; + return *this; +} + AbstractTask& asst::AbstractTask::set_task_id(int task_id) noexcept { m_task_id = task_id; diff --git a/src/MeoAssistant/AbstractTask.h b/src/MeoAssistant/AbstractTask.h index aadf82b168..b7466492ad 100644 --- a/src/MeoAssistant/AbstractTask.h +++ b/src/MeoAssistant/AbstractTask.h @@ -36,6 +36,7 @@ namespace asst virtual AbstractTask& set_ctrler(std::shared_ptr ctrler) noexcept; virtual AbstractTask& set_status(std::shared_ptr status) noexcept; virtual AbstractTask& set_enable(bool enable) noexcept; + virtual AbstractTask& set_ignore_error(bool ignore) noexcept; virtual AbstractTask& set_task_id(int task_id) noexcept; template @@ -51,6 +52,7 @@ namespace asst void clear_plugin() noexcept; bool get_enable() const noexcept { return m_enable; } + bool get_ignore_error() const noexcept { return m_ignore_error; } const std::string& get_task_chain() const noexcept { return m_task_chain; } int get_task_id() const noexcept { return m_task_id; } virtual json::value basic_info() const; @@ -68,6 +70,7 @@ namespace asst bool save_image(const cv::Mat image, const std::string& dir); bool m_enable = true; + bool m_ignore_error = true; AsstCallback m_callback; void* m_callback_arg = nullptr; bool* m_exit_flag = nullptr; diff --git a/src/MeoAssistant/CopilotTask.cpp b/src/MeoAssistant/CopilotTask.cpp index 6c186b0504..55c98f8a28 100644 --- a/src/MeoAssistant/CopilotTask.cpp +++ b/src/MeoAssistant/CopilotTask.cpp @@ -6,37 +6,37 @@ #include "BattleFormationTask.h" asst::CopilotTask::CopilotTask(AsstCallback callback, void* callback_arg) - : PackageTask(callback, callback_arg, TaskType), - m_battle_task_ptr(std::make_shared(callback, callback_arg, TaskType)), - m_formation_task_ptr(std::make_shared(callback, callback_arg, TaskType)) + : PackageTask(callback, callback_arg, TaskType), + m_formation_task_ptr(std::make_shared(callback, callback_arg, TaskType)), + m_battle_task_ptr(std::make_shared(callback, callback_arg, TaskType)) { - m_subtasks.emplace_back(m_formation_task_ptr); + m_subtasks.emplace_back(m_formation_task_ptr)->set_ignore_error(false); - auto start_task_ptr = std::make_shared(callback, callback_arg, TaskType); - start_task_ptr->set_tasks({ "BattleStartNormal", "BattleStartRaid", "BattleStartExercise" }); - m_subtasks.emplace_back(start_task_ptr); + auto start_task_ptr = std::make_shared(callback, callback_arg, TaskType); + start_task_ptr->set_tasks({ "BattleStartNormal", "BattleStartRaid", "BattleStartExercise" }); + m_subtasks.emplace_back(start_task_ptr)->set_ignore_error(false); - m_subtasks.emplace_back(m_battle_task_ptr); + m_subtasks.emplace_back(m_battle_task_ptr); } bool asst::CopilotTask::set_params(const json::value& params) { - if (m_runned) { - return false; - } + if (m_runned) { + return false; + } - if (!params.contains("stage_name") || !params.at("stage_name").is_string()) { - return false; - } - std::string stage_name = params.at("stage_name").as_string(); + if (!params.contains("stage_name") || !params.at("stage_name").is_string()) { + return false; + } + std::string stage_name = params.at("stage_name").as_string(); - m_battle_task_ptr->set_stage_name(stage_name); - m_formation_task_ptr->set_stage_name(stage_name); + m_battle_task_ptr->set_stage_name(stage_name); + m_formation_task_ptr->set_stage_name(stage_name); - bool with_formation = params.get("formation", false); - m_formation_task_ptr->set_enable(with_formation); + bool with_formation = params.get("formation", false); + m_formation_task_ptr->set_enable(with_formation); - std::string filename = params.get("filename", std::string()); - // 文件名为空时,不加载资源,直接返回 true - return filename.empty() || Resrc.copilot().load(filename); -} \ No newline at end of file + std::string filename = params.get("filename", std::string()); + // 文件名为空时,不加载资源,直接返回 true + return filename.empty() || Resrc.copilot().load(filename); +} diff --git a/src/MeoAssistant/FightTask.cpp b/src/MeoAssistant/FightTask.cpp index c176ce88c4..98b7f3df9d 100644 --- a/src/MeoAssistant/FightTask.cpp +++ b/src/MeoAssistant/FightTask.cpp @@ -17,7 +17,8 @@ asst::FightTask::FightTask(AsstCallback callback, void* callback_arg) .set_times_limit("MedicineConfirm", 0) .set_times_limit("StoneConfirm", 0) .set_times_limit("StageSNReturnFlag", 0) - .set_enable(false); + .set_enable(false) + .set_ignore_error(false); // 进入对应的关卡 m_stage_task_ptr->set_times_limit("StartButton1", 0) @@ -25,7 +26,8 @@ asst::FightTask::FightTask(AsstCallback callback, void* callback_arg) .set_times_limit("MedicineConfirm", 0) .set_times_limit("StoneConfirm", 0) .set_times_limit("StageSNReturnFlag", 0) - .set_enable(false); + .set_enable(false) + .set_ignore_error(false); // 开始战斗任务 m_fight_task_ptr->set_tasks({ "FightBegin" }) diff --git a/src/MeoAssistant/PackageTask.cpp b/src/MeoAssistant/PackageTask.cpp index 1370cb4fb1..31050e3afb 100644 --- a/src/MeoAssistant/PackageTask.cpp +++ b/src/MeoAssistant/PackageTask.cpp @@ -28,7 +28,7 @@ bool asst::PackageTask::run() .set_status(m_status) .set_task_id(m_task_id); - if (!task_ptr->run()) { + if (!task_ptr->run() && !task_ptr->get_ignore_error()) { return false; } From 7ebc78b91e2702ad0b95e60d35b303328e8b39a8 Mon Sep 17 00:00:00 2001 From: MistEO Date: Sat, 14 May 2022 02:52:51 +0800 Subject: [PATCH 24/31] =?UTF-8?q?fix.=E4=BF=AE=E5=A4=8D=E5=85=AC=E6=8B=9B?= =?UTF-8?q?=E5=88=B8=E4=B8=8D=E8=B6=B3=E6=97=B6=E5=8D=A1=E5=BE=88=E4=B9=85?= =?UTF-8?q?=E6=89=8D=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/AutoRecruitTask.cpp | 2 +- src/MeoAssistant/RecruitTask.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MeoAssistant/AutoRecruitTask.cpp b/src/MeoAssistant/AutoRecruitTask.cpp index e1cbf75246..7187911d49 100644 --- a/src/MeoAssistant/AutoRecruitTask.cpp +++ b/src/MeoAssistant/AutoRecruitTask.cpp @@ -185,7 +185,7 @@ bool asst::AutoRecruitTask::recruit_now() bool asst::AutoRecruitTask::confirm() { ProcessTask confirm_task(*this, { "RecruitConfirm" }); - return confirm_task.run(); + return confirm_task.set_retry_times(5).run(); } bool asst::AutoRecruitTask::refresh() diff --git a/src/MeoAssistant/RecruitTask.cpp b/src/MeoAssistant/RecruitTask.cpp index b47bdb4fb2..142fa22822 100644 --- a/src/MeoAssistant/RecruitTask.cpp +++ b/src/MeoAssistant/RecruitTask.cpp @@ -14,7 +14,7 @@ asst::RecruitTask::RecruitTask(AsstCallback callback, void* callback_arg) m_recruit_only_calc_task_ptr->set_enable(false); m_subtasks.emplace_back(m_recruit_begin_task_ptr); - m_subtasks.emplace_back(m_auto_recruit_task_ptr); + m_subtasks.emplace_back(m_auto_recruit_task_ptr)->set_retry_times(1); m_subtasks.emplace_back(m_recruit_only_calc_task_ptr); } From cd98e78ebb71e03edf7c61eb7dc19ec3419441e0 Mon Sep 17 00:00:00 2001 From: MistEO Date: Sat, 14 May 2022 03:54:21 +0800 Subject: [PATCH 25/31] =?UTF-8?q?perf.=E4=BB=A5=E4=B8=80=E7=A7=8D=E6=9B=B4?= =?UTF-8?q?=E5=8A=A0=E4=BC=98=E9=9B=85=E7=9A=84=E6=96=B9=E5=BC=8F=E7=94=9F?= =?UTF-8?q?=E6=88=90=E7=89=88=E6=9C=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/MeoAssistant.vcxproj | 2 +- src/MeoAssistant/Version.h | 7 ++++++- tools/build_release.bat | 2 +- tools/version.sh | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/MeoAssistant/MeoAssistant.vcxproj b/src/MeoAssistant/MeoAssistant.vcxproj index 1bf1ec98b3..57301506fc 100644 --- a/src/MeoAssistant/MeoAssistant.vcxproj +++ b/src/MeoAssistant/MeoAssistant.vcxproj @@ -248,7 +248,7 @@ stdc11 MultiThreaded MaxSpeed - /utf-8 /MP %(AdditionalOptions) + /utf-8 /MP $(ExternalCompilerOptions) %(AdditionalOptions) true diff --git a/src/MeoAssistant/Version.h b/src/MeoAssistant/Version.h index de415f9699..c24e3b7c70 100644 --- a/src/MeoAssistant/Version.h +++ b/src/MeoAssistant/Version.h @@ -2,5 +2,10 @@ namespace asst { - constexpr static const char* Version = "DEBUG VERSION"; + constexpr static const char* Version = +#ifdef MAA_VERSION + MAA_VERSION; +#else + "DEBUG VERSION"; +#endif } diff --git a/tools/build_release.bat b/tools/build_release.bat index e00d15e635..ebafb944ae 100644 --- a/tools/build_release.bat +++ b/tools/build_release.bat @@ -1,4 +1,4 @@ -sh ./update_version.sh +for /f "delims=" %%i in ('sh ./version.sh') do set ExternalCompilerOptions=/DMAA_VERSION=\"%%i\" MSBuild.exe ..\MeoAssistantArknights.sln /p:Configuration=Release /p:Platform=x64 /t:Rebuild call .\update_resource_rel.bat pause diff --git a/tools/version.sh b/tools/version.sh index f85663a5f9..d3610e1d10 100644 --- a/tools/version.sh +++ b/tools/version.sh @@ -9,4 +9,4 @@ else Version="c""$LatestCommitId" fi -echo "Version: $Version" +echo "$Version" From 48817ecc8c1f97bd9591fde5dd200cdb0c523d22 Mon Sep 17 00:00:00 2001 From: zzyyyl <74587068+zzyyyl@users.noreply.github.com> Date: Sat, 14 May 2022 12:58:49 +0800 Subject: [PATCH 26/31] =?UTF-8?q?style.=E5=A2=9E=E5=8A=A0=E4=B8=80?= =?UTF-8?q?=E4=B8=AA`.gitattributes`=E6=96=87=E4=BB=B6=E7=94=A8=E4=BA=8E?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..6dcdb8d26e --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +* text=auto +*.cs text eol=crlf +*.xaml text eol=crlf + +*.cpp text eol=lf +*.hpp text eol=lf +*.h text eol=lf + +*.json text eol=lf +*.md text eol=lf +*.yaml text eol=lf From 05052a0b565687ff5ba47586053175df00140125 Mon Sep 17 00:00:00 2001 From: zzyyyl <74587068+zzyyyl@users.noreply.github.com> Date: Sat, 14 May 2022 12:52:27 +0800 Subject: [PATCH 27/31] =?UTF-8?q?fix.=E4=BF=AE=E5=A4=8D=E7=AC=94=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/AsstCaller.cpp | 4 ++++ src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/MeoAssistant/AsstCaller.cpp b/src/MeoAssistant/AsstCaller.cpp index 602cf788e0..43165632fc 100644 --- a/src/MeoAssistant/AsstCaller.cpp +++ b/src/MeoAssistant/AsstCaller.cpp @@ -85,7 +85,11 @@ bool AsstConnect(AsstHandle handle, const char* adb_path, const char* address, c return false; } +#ifdef _WIN32 return handle->connect(asst::utils::utf8_to_gbk(adb_path), address, config ? config : std::string()); +#else + return handle->connect(adb_path, address, config ? config : std::string()); +#endif } bool AsstStart(AsstHandle handle) diff --git a/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs b/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs index 1a0cb763d0..04820a5e04 100644 --- a/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs +++ b/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs @@ -294,7 +294,7 @@ namespace MeoAsstGui private bool appendMall() { var settings = _container.Get(); - var asstProxy = _container.Get(); + var asstProxy = _container.Get(); var buy_first = settings.CreditFirstList.Split(' '); var black_list = settings.CreditBlackList.Split(' '); return asstProxy.AsstAppendMall(settings.CreditShopping, buy_first, black_list); From 27a91aee672b4de5e7210c2f4038b62bbc7422a1 Mon Sep 17 00:00:00 2001 From: zzyyyl <74587068+zzyyyl@users.noreply.github.com> Date: Sat, 14 May 2022 13:22:47 +0800 Subject: [PATCH 28/31] =?UTF-8?q?perf.=E5=B0=8F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/AbstractConfiger.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/MeoAssistant/AbstractConfiger.cpp b/src/MeoAssistant/AbstractConfiger.cpp index 09bd2031e9..2e45d06412 100644 --- a/src/MeoAssistant/AbstractConfiger.cpp +++ b/src/MeoAssistant/AbstractConfiger.cpp @@ -9,18 +9,17 @@ bool asst::AbstractConfiger::load(const std::string& filename) { LogTraceFunction; - std::string cvt_filename = filename; -#ifdef WIN32 - Log.info("Load:", utils::gbk_2_utf8(cvt_filename)); +#ifdef _WIN32 + Log.info("Load:", utils::gbk_2_utf8(filename)); #else - Log.info("Load:", cvt_filename); + Log.info("Load:", filename); #endif - if (!std::filesystem::exists(cvt_filename)) { + if (!std::filesystem::exists(filename)) { return false; } - std::string content = utils::load_file_without_bom(cvt_filename); + std::string content = utils::load_file_without_bom(filename); auto&& ret = json::parser::parse(content); if (!ret) { From d967a2cf9defeafb93a632842c6db95a9075093d Mon Sep 17 00:00:00 2001 From: MistEO Date: Sat, 14 May 2022 15:56:22 +0800 Subject: [PATCH 29/31] =?UTF-8?q?chore.=E5=8A=A0=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E7=82=B9=E6=97=A5=E5=BF=97=E4=BB=A5=E8=BF=BD=E8=B8=AA=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20issues/502?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues/502 --- src/MeoAssistant/InfrastProductionTask.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/MeoAssistant/InfrastProductionTask.cpp b/src/MeoAssistant/InfrastProductionTask.cpp index 342f1d18f5..28f8ea8541 100644 --- a/src/MeoAssistant/InfrastProductionTask.cpp +++ b/src/MeoAssistant/InfrastProductionTask.cpp @@ -556,10 +556,7 @@ bool asst::InfrastProductionTask::opers_choose() [&](const infrast::BattleRealTimeOper& lhs) -> bool { int dist = HashImageAnalyzer::hamming(lhs.face_hash, find_iter->face_hash); Log.debug("opers_choose | face hash dist", dist); - if (dist < face_hash_thres) { - return true; - } - return false; + return dist < face_hash_thres; } ); if (avlb_iter != m_all_available_opers.cend()) { @@ -574,13 +571,12 @@ bool asst::InfrastProductionTask::opers_choose() opt_iter = m_optimal_combs.erase(opt_iter); } if (m_optimal_combs.empty()) { - if (count >= cur_max_num_of_opers) { - break; - } - else { // 这种情况可能是萌新,可用干员人数不足以填满当前设施 + Log.trace(__FUNCTION__, "| count", count, "cur_max_num_of_opers", cur_max_num_of_opers); + if (count < cur_max_num_of_opers) { + // 这种情况可能是萌新,可用干员人数不足以填满当前设施 callback(AsstMsg::SubTaskExtraInfo, basic_info_with_what("NotEnoughStaff")); - break; } + break; } // 因为识别完了还要点击,所以这里不能异步滑动 From 4f05a45d6b45623590fa7d18f4dea4780e5872fa Mon Sep 17 00:00:00 2001 From: MistEO Date: Sat, 14 May 2022 16:02:03 +0800 Subject: [PATCH 30/31] =?UTF-8?q?perf.=E6=9B=B4=E6=96=B0=E7=BC=A9=E6=94=BE?= =?UTF-8?q?=E5=9B=BE=E5=83=8F=E7=9A=84=E6=8F=92=E5=80=BC=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/Controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index 2ecef395c9..26b6bb0dc5 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -512,7 +512,7 @@ cv::Mat asst::Controller::get_resized_image() const return cv::Mat(dsize, CV_8UC3); } cv::Mat resized_mat; - cv::resize(m_cache_image, resized_mat, dsize); + cv::resize(m_cache_image, resized_mat, dsize, 0.0, 0.0, cv::INTER_AREA); return resized_mat; } From a99119c263db204d57a6d2cb4fc0bca55d1525ab Mon Sep 17 00:00:00 2001 From: MistEO Date: Sun, 15 May 2022 14:22:01 +0800 Subject: [PATCH 31/31] =?UTF-8?q?style.=E6=A0=BC=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/AsstUtils.hpp | 4 +- src/MeoAssistant/GeneralConfiger.cpp | 76 +- src/MeoAssistant/StageDropsTaskPlugin.cpp | 1 - src/MeoAssistant/TilePack.cpp | 4 +- src/MeoAssistantBuilder/Constants.cs | 4 +- .../Helper/CleanDirectoryHelper.cs | 1 + src/MeoAssistantBuilder/MaaBuildContext.cs | 2 +- src/MeoAssistantBuilder/Tasks/DevBuildTask.cs | 1 - .../Tasks/ReleaseBundleTask.cs | 2 +- .../Tasks/ReleaseCoreTask.cs | 4 +- .../Tasks/ReleaseResourceTask.cs | 1 - .../Tasks/ReleaseWpfTask.cs | 1 - src/MeoAsstGui/Helper/AsstProxy.cs | 1394 +++++++------- src/MeoAsstGui/Helper/ScrollViewerBinding.cs | 2 - src/MeoAsstGui/Helper/ToastNotification.cs | 23 +- src/MeoAsstGui/Helper/ViewStatusStorage.cs | 168 +- .../UserControl/ToastSettingsUserControl.xaml | 3 +- src/MeoAsstGui/ViewModels/RecruitViewModel.cs | 316 ++-- src/MeoAsstGui/ViewModels/RootViewModel.cs | 180 +- .../ViewModels/SettingsViewModel.cs | 1684 ++++++++--------- .../ViewModels/VersionUpdateViewModel.cs | 1390 +++++++------- 21 files changed, 2628 insertions(+), 2633 deletions(-) diff --git a/src/MeoAssistant/AsstUtils.hpp b/src/MeoAssistant/AsstUtils.hpp index 475679fdab..2d3ce27916 100644 --- a/src/MeoAssistant/AsstUtils.hpp +++ b/src/MeoAssistant/AsstUtils.hpp @@ -307,5 +307,5 @@ namespace asst // } // return str; //} - } - } + } +} diff --git a/src/MeoAssistant/GeneralConfiger.cpp b/src/MeoAssistant/GeneralConfiger.cpp index 9af27cee4f..47c372bcb1 100644 --- a/src/MeoAssistant/GeneralConfiger.cpp +++ b/src/MeoAssistant/GeneralConfiger.cpp @@ -5,50 +5,50 @@ bool asst::GeneralConfiger::parse(const json::value& json) { - LogTraceFunction; + LogTraceFunction; - m_version = json.at("version").as_string(); + m_version = json.at("version").as_string(); - { - const json::value& options_json = json.at("options"); - m_options.task_delay = options_json.at("taskDelay").as_integer(); - m_options.control_delay_lower = options_json.at("controlDelayRange")[0].as_integer(); - m_options.control_delay_upper = options_json.at("controlDelayRange")[1].as_integer(); - //m_options.print_window = options_json.at("printWindow").as_boolean(); - m_options.adb_extra_swipe_dist = options_json.get("adbExtraSwipeDist", 100); - m_options.adb_extra_swipe_duration = options_json.get("adbExtraSwipeDuration", -1); + { + const json::value& options_json = json.at("options"); + m_options.task_delay = options_json.at("taskDelay").as_integer(); + m_options.control_delay_lower = options_json.at("controlDelayRange")[0].as_integer(); + m_options.control_delay_upper = options_json.at("controlDelayRange")[1].as_integer(); + //m_options.print_window = options_json.at("printWindow").as_boolean(); + m_options.adb_extra_swipe_dist = options_json.get("adbExtraSwipeDist", 100); + m_options.adb_extra_swipe_duration = options_json.get("adbExtraSwipeDuration", -1); - auto& penguin_report = options_json.at("penguinReport"); - m_options.penguin_report.cmd_format = penguin_report.get("cmdFormat", std::string()); + auto& penguin_report = options_json.at("penguinReport"); + m_options.penguin_report.cmd_format = penguin_report.get("cmdFormat", std::string()); - if (options_json.contains("aipOcr")) { - auto& aip_ocr = options_json.at("aipOcr"); - m_options.aip_ocr.enable = aip_ocr.get("enable", false); - m_options.aip_ocr.accurate = aip_ocr.get("accurate", false); - m_options.aip_ocr.client_id = aip_ocr.get("clientId", std::string()); - m_options.aip_ocr.client_secret = aip_ocr.get("clientSerect", std::string()); - } - } + if (options_json.contains("aipOcr")) { + auto& aip_ocr = options_json.at("aipOcr"); + m_options.aip_ocr.enable = aip_ocr.get("enable", false); + m_options.aip_ocr.accurate = aip_ocr.get("accurate", false); + m_options.aip_ocr.client_id = aip_ocr.get("clientId", std::string()); + m_options.aip_ocr.client_secret = aip_ocr.get("clientSerect", std::string()); + } + } - for (const auto& [name, cfg_json] : json.at("connection").as_object()) { - AdbCfg adb; + for (const auto& [name, cfg_json] : json.at("connection").as_object()) { + AdbCfg adb; - adb.devices = cfg_json.at("devices").as_string(); - adb.address_regex = cfg_json.at("addressRegex").as_string(); - adb.connect = cfg_json.at("connect").as_string(); - adb.display_id = cfg_json.get("displayId", std::string()); - adb.uuid = cfg_json.at("uuid").as_string(); - adb.click = cfg_json.at("click").as_string(); - adb.swipe = cfg_json.at("swipe").as_string(); - adb.display = cfg_json.at("display").as_string(); - adb.display_format = cfg_json.at("displayFormat").as_string(); - adb.screencap_raw_with_gzip = cfg_json.at("screencapRawWithGzip").as_string(); - adb.screencap_encode = cfg_json.at("screencapEncode").as_string(); - adb.release = cfg_json.at("release").as_string(); - //adb.pullscreen = cfg_json.at("pullscreen").as_string(); + adb.devices = cfg_json.at("devices").as_string(); + adb.address_regex = cfg_json.at("addressRegex").as_string(); + adb.connect = cfg_json.at("connect").as_string(); + adb.display_id = cfg_json.get("displayId", std::string()); + adb.uuid = cfg_json.at("uuid").as_string(); + adb.click = cfg_json.at("click").as_string(); + adb.swipe = cfg_json.at("swipe").as_string(); + adb.display = cfg_json.at("display").as_string(); + adb.display_format = cfg_json.at("displayFormat").as_string(); + adb.screencap_raw_with_gzip = cfg_json.at("screencapRawWithGzip").as_string(); + adb.screencap_encode = cfg_json.at("screencapEncode").as_string(); + adb.release = cfg_json.at("release").as_string(); + //adb.pullscreen = cfg_json.at("pullscreen").as_string(); - m_adb_cfg[name] = std::move(adb); - } + m_adb_cfg[name] = std::move(adb); + } - return true; + return true; } diff --git a/src/MeoAssistant/StageDropsTaskPlugin.cpp b/src/MeoAssistant/StageDropsTaskPlugin.cpp index 3eb742638b..0ad9fc2ff4 100644 --- a/src/MeoAssistant/StageDropsTaskPlugin.cpp +++ b/src/MeoAssistant/StageDropsTaskPlugin.cpp @@ -110,7 +110,6 @@ bool asst::StageDropsTaskPlugin::recognize_drops() auto last_time = last_time_opt ? last_time_opt.value() : 0; m_status->set_data("LastRecognizeDrops", last_time + RecognizationTimeOffset); - return true; } diff --git a/src/MeoAssistant/TilePack.cpp b/src/MeoAssistant/TilePack.cpp index aeb67e0ee2..2798da9313 100644 --- a/src/MeoAssistant/TilePack.cpp +++ b/src/MeoAssistant/TilePack.cpp @@ -6,7 +6,7 @@ asst::TilePack::~TilePack() = default; -bool asst::TilePack::load(const std::string & dir) +bool asst::TilePack::load(const std::string& dir) { LogTraceFunction; @@ -28,7 +28,7 @@ bool asst::TilePack::load(const std::string & dir) } std::unordered_map asst::TilePack::calc( - const std::string & stage_code, bool side) const + const std::string& stage_code, bool side) const { LogTraceFunction; diff --git a/src/MeoAssistantBuilder/Constants.cs b/src/MeoAssistantBuilder/Constants.cs index 7b67b1daf4..52811043bb 100644 --- a/src/MeoAssistantBuilder/Constants.cs +++ b/src/MeoAssistantBuilder/Constants.cs @@ -14,10 +14,10 @@ public static class Constants public const string MaaWpfProjectFilePath = $"{MaaWpfProjectDirectory}/MeoAsstGui.csproj"; public const string MaaBuildOutputDirectory = $"{MaaProjectRootDirectory}/x64"; - + public const string MaaCoreBuildIntermediatOutputDirectory = $"{MaaCoreProjectDirectory}/x64"; - public static readonly string[] MaaCoreExtraFiles = new [] { "MeoAssistant.pdb", "MeoAssistant.lib", "MeoAssistant.exp" }; + public static readonly string[] MaaCoreExtraFiles = new[] { "MeoAssistant.pdb", "MeoAssistant.lib", "MeoAssistant.exp" }; public static readonly string[] MaaWpfExtraFiles = new[] { "MeoAsstGui.pdb", "MeoAsstGui.exe.config" }; } diff --git a/src/MeoAssistantBuilder/Helper/CleanDirectoryHelper.cs b/src/MeoAssistantBuilder/Helper/CleanDirectoryHelper.cs index 44611e9631..48c5fa8ae9 100644 --- a/src/MeoAssistantBuilder/Helper/CleanDirectoryHelper.cs +++ b/src/MeoAssistantBuilder/Helper/CleanDirectoryHelper.cs @@ -2,6 +2,7 @@ using Cake.Common.Diagnostics; using Cake.Common.IO; namespace MeoAssistantBuilder.Helper; + public static class CleanDirectoryHelper { public static void CleanArtifacts(this MaaBuildContext context) diff --git a/src/MeoAssistantBuilder/MaaBuildContext.cs b/src/MeoAssistantBuilder/MaaBuildContext.cs index 01044eed84..ad393e1914 100644 --- a/src/MeoAssistantBuilder/MaaBuildContext.cs +++ b/src/MeoAssistantBuilder/MaaBuildContext.cs @@ -9,7 +9,7 @@ namespace MeoAssistantBuilder; public class MaaBuildContext : FrostingContext { public string MsBuildExecutable { get; set; } - + public MaaBuildContext(ICakeContext context) : base(context) { MsBuildExecutable = context.Argument("tool", ""); diff --git a/src/MeoAssistantBuilder/Tasks/DevBuildTask.cs b/src/MeoAssistantBuilder/Tasks/DevBuildTask.cs index 6b7ce804c7..1507ba06b2 100644 --- a/src/MeoAssistantBuilder/Tasks/DevBuildTask.cs +++ b/src/MeoAssistantBuilder/Tasks/DevBuildTask.cs @@ -1,4 +1,3 @@ -using Cake.Common.Build; using Cake.Common.Diagnostics; using Cake.Frosting; using MeoAssistantBuilder.Helper; diff --git a/src/MeoAssistantBuilder/Tasks/ReleaseBundleTask.cs b/src/MeoAssistantBuilder/Tasks/ReleaseBundleTask.cs index 1a75549b30..a1a056d509 100644 --- a/src/MeoAssistantBuilder/Tasks/ReleaseBundleTask.cs +++ b/src/MeoAssistantBuilder/Tasks/ReleaseBundleTask.cs @@ -45,7 +45,7 @@ public sealed class ReleaseBundleTask : FrostingTask { version += $"-{ghActions.Environment.Workflow.RunId}"; } - else + else { var tag = ghActions.Environment.Workflow.Ref.Replace("refs/tags/", ""); if (tag != version) diff --git a/src/MeoAssistantBuilder/Tasks/ReleaseCoreTask.cs b/src/MeoAssistantBuilder/Tasks/ReleaseCoreTask.cs index 8a2131b5e4..ad4fe1d1e3 100644 --- a/src/MeoAssistantBuilder/Tasks/ReleaseCoreTask.cs +++ b/src/MeoAssistantBuilder/Tasks/ReleaseCoreTask.cs @@ -45,7 +45,7 @@ public sealed class ReleaseCoreTask : FrostingTask { version += $"-{ghActions.Environment.Workflow.RunId}"; } - else + else { var tag = ghActions.Environment.Workflow.Ref.Replace("refs/tags/", ""); if (tag != version) @@ -78,7 +78,7 @@ public sealed class ReleaseCoreTask : FrostingTask context.Information("--------------------------------------------------"); var thirdPartyDlls = Directory.GetFiles(Path.Combine(Constants.MaaProjectThirdPartyDirectory, "bin")); - foreach(var f in thirdPartyDlls) + foreach (var f in thirdPartyDlls) { var fileName = new FileInfo(f).Name; File.Copy(f, Path.Combine(buildOutput, fileName)); diff --git a/src/MeoAssistantBuilder/Tasks/ReleaseResourceTask.cs b/src/MeoAssistantBuilder/Tasks/ReleaseResourceTask.cs index de89df2d60..744ff6247e 100644 --- a/src/MeoAssistantBuilder/Tasks/ReleaseResourceTask.cs +++ b/src/MeoAssistantBuilder/Tasks/ReleaseResourceTask.cs @@ -1,4 +1,3 @@ -using Cake.Common.Build; using Cake.Common.Diagnostics; using Cake.Frosting; using MeoAssistantBuilder.Helper; diff --git a/src/MeoAssistantBuilder/Tasks/ReleaseWpfTask.cs b/src/MeoAssistantBuilder/Tasks/ReleaseWpfTask.cs index 43b7ceb0b9..c12ccf6789 100644 --- a/src/MeoAssistantBuilder/Tasks/ReleaseWpfTask.cs +++ b/src/MeoAssistantBuilder/Tasks/ReleaseWpfTask.cs @@ -1,4 +1,3 @@ -using Cake.Common.Build; using Cake.Common.Diagnostics; using Cake.Frosting; using MeoAssistantBuilder.Helper; diff --git a/src/MeoAsstGui/Helper/AsstProxy.cs b/src/MeoAsstGui/Helper/AsstProxy.cs index 35101bf9ad..46e37ff562 100644 --- a/src/MeoAsstGui/Helper/AsstProxy.cs +++ b/src/MeoAsstGui/Helper/AsstProxy.cs @@ -1,697 +1,697 @@ -// MeoAsstGui - A part of the MeoAssistantArknights project -// Copyright (C) 2021 MistEO and Contributors -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY - -using System; -using System.Runtime.InteropServices; -using System.Text; -using System.Windows; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Stylet; -using StyletIoC; - -namespace MeoAsstGui -{ - using AsstHandle = IntPtr; - using TaskId = Int32; - - public class AsstProxy - { - private delegate void CallbackDelegate(int msg, IntPtr json_buffer, IntPtr custom_arg); - - private delegate void ProcCallbckMsg(AsstMsg msg, JObject details); - - [DllImport("MeoAssistant.dll")] private static extern bool AsstLoadResource(byte[] dirname); - - private static bool AsstLoadResource(string dirname) - { - return AsstLoadResource(Encoding.UTF8.GetBytes(dirname)); - } - - [DllImport("MeoAssistant.dll")] private static extern AsstHandle AsstCreate(); - - [DllImport("MeoAssistant.dll")] private static extern AsstHandle AsstCreateEx(CallbackDelegate callback, IntPtr custom_arg); - - [DllImport("MeoAssistant.dll")] private static extern void AsstDestroy(AsstHandle handle); - - [DllImport("MeoAssistant.dll")] private static extern bool AsstConnect(AsstHandle handle, byte[] adb_path, byte[] address, byte[] config); - - private static bool AsstConnect(AsstHandle handle, string adb_path, string address, string config) - { - return AsstConnect(handle, Encoding.UTF8.GetBytes(adb_path), Encoding.UTF8.GetBytes(address), Encoding.UTF8.GetBytes(config)); - } - - [DllImport("MeoAssistant.dll")] private static extern TaskId AsstAppendTask(AsstHandle handle, byte[] type, byte[] task_params); - - private static TaskId AsstAppendTask(AsstHandle handle, string type, string task_params) - { - return AsstAppendTask(handle, Encoding.UTF8.GetBytes(type), Encoding.UTF8.GetBytes(task_params)); - } - - [DllImport("MeoAssistant.dll")] private static extern bool AsstSetTaskParams(AsstHandle handle, TaskId id, byte[] task_params); - - [DllImport("MeoAssistant.dll")] private static extern bool AsstStart(AsstHandle handle); - - [DllImport("MeoAssistant.dll")] private static extern bool AsstStop(AsstHandle handle); - - [DllImport("MeoAssistant.dll")] private static extern void AsstLog(byte[] level, byte[] message); - - private readonly CallbackDelegate _callback; - - public AsstProxy(IContainer container, IWindowManager windowManager) - { - _container = container; - _windowManager = windowManager; - _callback = CallbackFunction; - } - - public void Init() - { - bool loaded = AsstLoadResource(System.IO.Directory.GetCurrentDirectory()); - _handle = AsstCreateEx(_callback, IntPtr.Zero); - - if (loaded == false || _handle == IntPtr.Zero) - { - Execute.OnUIThread(() => - { - _windowManager.ShowMessageBox("出现未知异常", "错误", icon: MessageBoxImage.Error); - Environment.Exit(0); - }); - } - var tvm = _container.Get(); - tvm.Idle = true; - } - - [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true)] - internal static extern int lstrlenA(IntPtr ptr); - - private static string PtrToStringCustom(IntPtr ptr, System.Text.Encoding enc) - { - if (IntPtr.Zero == ptr) - { - return null; - } - if (lstrlenA(ptr) == 0) - { - return string.Empty; - } - int len = lstrlenA(ptr); - Byte[] bytes = new Byte[len + 1]; - Marshal.Copy(ptr, bytes, 0, len + 1); - return enc.GetString(bytes); - } - - private void CallbackFunction(int msg, IntPtr json_buffer, IntPtr custom_arg) - { - string json_str = PtrToStringCustom(json_buffer, System.Text.Encoding.UTF8); - //Console.WriteLine(json_str); - JObject json = (JObject)JsonConvert.DeserializeObject(json_str); - ProcCallbckMsg dlg = new ProcCallbckMsg(procMsg); - Execute.OnUIThread(() => - { - dlg((AsstMsg)msg, json); - }); - } - - private readonly IWindowManager _windowManager; - private readonly IContainer _container; - private IntPtr _handle; - - private void procMsg(AsstMsg msg, JObject details) - { - switch (msg) - { - case AsstMsg.InternalError: - break; - - case AsstMsg.InitFailed: - _windowManager.ShowMessageBox("初始化错误!请检查是否使用了中文路径", "错误", icon: MessageBoxImage.Error); - Environment.Exit(0); - break; - - case AsstMsg.ConnectionError: - break; - - case AsstMsg.AllTasksCompleted: - case AsstMsg.TaskChainError: - case AsstMsg.TaskChainStart: - case AsstMsg.TaskChainCompleted: - case AsstMsg.TaskChainExtraInfo: - procTaskChainMsg(msg, details); - break; - - case AsstMsg.SubTaskError: - case AsstMsg.SubTaskStart: - case AsstMsg.SubTaskCompleted: - case AsstMsg.SubTaskExtraInfo: - procSubTaskMsg(msg, details); - break; - } - } - - private void procTaskChainMsg(AsstMsg msg, JObject details) - { - string taskChain = details["taskchain"].ToString(); - - if (taskChain == "Recruit") - { - if (msg == AsstMsg.TaskChainError) - { - var recruitModel = _container.Get(); - recruitModel.RecruitInfo = "识别错误!"; - } - } - var mainModel = _container.Get(); - - switch (msg) - { - case AsstMsg.TaskChainError: - mainModel.AddLog("任务出错:" + taskChain, "darkred"); - break; - - case AsstMsg.TaskChainStart: - mainModel.AddLog("开始任务:" + taskChain); - break; - - case AsstMsg.TaskChainCompleted: - mainModel.AddLog("完成任务:" + taskChain); - break; - - case AsstMsg.TaskChainExtraInfo: - break; - - case AsstMsg.AllTasksCompleted: - mainModel.Idle = true; - mainModel.AddLog("任务已全部完成"); - mainModel.UseStone = false; - using (var toast = new ToastNotification("任务已全部完成!")) - { - toast.Show(); - } - mainModel.CheckAndShutdown(); - break; - } - } - - private void procSubTaskMsg(AsstMsg msg, JObject details) - { - // 下面几行注释暂时没用到,先注释起来... - //string taskChain = details["taskchain"].ToString(); - //string classType = details["class"].ToString(); - - //var mainModel = _container.Get(); - switch (msg) - { - case AsstMsg.SubTaskError: - procSubTaskError(details); - break; - - case AsstMsg.SubTaskStart: - procSubTaskStart(details); - break; - - case AsstMsg.SubTaskCompleted: - procSubTaskCompleted(details); - break; - - case AsstMsg.SubTaskExtraInfo: - procSubTaskExtraInfo(details); - break; - } - } - - private void procSubTaskError(JObject details) - { - string subTask = details["subtask"].ToString(); - - var mainModel = _container.Get(); - - switch (subTask) - { - case "AutoRecruitTask": - mainModel.AddLog("公招识别错误,已返回", "darkred"); - break; - - //case "StageDropsTask": - // mainModel.AddLog("关卡识别错误", "darkred"); - // break; - - case "ReportToPenguinStats": - mainModel.AddLog("上传企鹅数据错误", "darkred"); - break; - - case "CheckStageValid": - mainModel.AddLog("EX 关卡,已停止", "darkred"); - break; - } - } - - private void procSubTaskStart(JObject details) - { - string subTask = details["subtask"].ToString(); - - var mainModel = _container.Get(); - if (subTask == "ProcessTask") - { - string taskName = details["details"]["task"].ToString(); - int execTimes = (int)details["details"]["exec_times"]; - - switch (taskName) - { - case "StartButton2": - mainModel.AddLog("已开始行动 " + execTimes + " 次", "darkcyan"); - break; - - case "MedicineConfirm": - mainModel.AddLog("已吃药 " + execTimes + " 个", "darkcyan"); - break; - - case "StoneConfirm": - mainModel.AddLog("已碎石 " + execTimes + " 颗", "darkcyan"); - break; - - case "AbandonAction": - mainModel.AddLog("代理指挥失误", "darkred"); - break; - - case "RecruitRefreshConfirm": - mainModel.AddLog("已刷新标签", "darkcyan"); - break; - - case "RecruitConfirm": - mainModel.AddLog("已确认招募", "darkcyan"); - break; - - case "InfrastDormDoubleConfirmButton": - mainModel.AddLog("干员冲突", "darkred"); - break; - - /* 肉鸽相关 */ - case "Roguelike1Start": - mainModel.AddLog("已开始探索 " + execTimes + " 次", "darkcyan"); - break; - - case "Roguelike1StageTraderInvestConfirm": - mainModel.AddLog("已投资 " + execTimes + " 个源石锭", "darkcyan"); - break; - - case "Roguelike1ExitThenAbandon": - mainModel.AddLog("已放弃本次探索"); - break; - - //case "Roguelike1StartAction": - // mainModel.AddLog("开始战斗"); - // break; - - case "Roguelike1MissionCompletedFlag": - mainModel.AddLog("战斗完成"); - break; - - case "Roguelike1MissionFailedFlag": - mainModel.AddLog("战斗失败"); - break; - - case "Roguelike1StageTraderEnter": - mainModel.AddLog("关卡:诡异行商"); - break; - - case "Roguelike1StageSafeHouseEnter": - mainModel.AddLog("关卡:安全的角落"); - break; - - case "Roguelike1StageEncounterEnter": - mainModel.AddLog("关卡:不期而遇/古堡馈赠"); - break; - - //case "Roguelike1StageBoonsEnter": - // mainModel.AddLog("古堡馈赠"); - // break; - - case "Roguelike1StageCambatDpsEnter": - mainModel.AddLog("关卡:普通作战"); - break; - - case "Roguelike1StageEmergencyDps": - mainModel.AddLog("关卡:紧急作战"); - break; - - case "Roguelike1StageDreadfulFoe": - mainModel.AddLog("关卡:险路恶敌"); - break; - - case "Roguelike1StageTraderInvestSystemFull": - mainModel.AddLog("投资达到上限", "darkcyan"); - break; - } - } - } - - private void procSubTaskCompleted(JObject details) - { - } - - private void procSubTaskExtraInfo(JObject details) - { - string taskChain = details["taskchain"].ToString(); - - if (taskChain == "Recruit") - { - procRecruitCalcMsg(details); - } - - string what = details["what"].ToString(); - var subTaskDetails = details["details"]; - - var mainModel = _container.Get(); - switch (what) - { - case "StageDrops": - { - string cur_drops = string.Empty; - JArray drops = (JArray)subTaskDetails["drops"]; - foreach (var item in drops) - { - string itemName = item["itemName"].ToString(); - int count = (int)item["quantity"]; - cur_drops += $"{itemName} : {count}\n"; - } - cur_drops = cur_drops.EndsWith("\n") ? cur_drops.TrimEnd('\n') : "无"; - mainModel.AddLog("当次掉落:\n" + cur_drops); - - string all_drops = string.Empty; - JArray statistics = (JArray)subTaskDetails["stats"]; - foreach (var item in statistics) - { - string itemName = item["itemName"].ToString(); - int count = (int)item["quantity"]; - all_drops += $"{itemName} : {count}\n"; - } - all_drops = all_drops.EndsWith("\n") ? all_drops.TrimEnd('\n') : "无"; - mainModel.AddLog("掉落统计:\n" + all_drops); - } - break; - - case "EnterFacility": - mainModel.AddLog("当前设施:" + subTaskDetails["facility"] + " " + (int)subTaskDetails["index"]); - break; - - case "RecruitTagsDetected": - { - JArray tags = (JArray)subTaskDetails["tags"]; - string log_content = string.Empty; - foreach (var tag_name in tags) - { - string tag_str = tag_name.ToString(); - log_content += tag_str + "\n"; - } - log_content = log_content.EndsWith("\n") ? log_content.TrimEnd('\n') : "错误"; - mainModel.AddLog("公招识别结果:\n" + log_content); - } - break; - - case "RecruitSpecialTag": - { - string special = subTaskDetails["tag"].ToString(); - using (var toast = new ToastNotification("公招提示")) - { - toast.AppendContentText(special).ShowRecruit(); - } - } - break; - - case "RecruitResult": - { - int level = (int)subTaskDetails["level"]; - if (level >= 5) - { - using (var toast = new ToastNotification($"公招出 {level} 星了哦!")) - { - toast.AppendContentText(new string('★', level)).ShowRecruit(row: 2); - } - mainModel.AddLog(level + " 星 Tags", "darkorange", "Bold"); - } - else - { - mainModel.AddLog(level + " 星 Tags", "darkcyan"); - } - } - break; - - case "RecruitTagsSelected": - { - JArray selected = (JArray)subTaskDetails["tags"]; - string selected_log = string.Empty; - foreach (var tag in selected) - { - selected_log += tag.ToString() + "\n"; - } - selected_log = selected_log.EndsWith("\n") ? selected_log.TrimEnd('\n') : "无"; - - mainModel.AddLog("选择 Tags:\n" + selected_log); - } - break; - - case "NotEnoughStaff": - { - mainModel.AddLog("可用干员不足", "darkred"); - } - break; - - /* Roguelike */ - case "StageInfo": - { - mainModel.AddLog("开始战斗:" + subTaskDetails["name"]); - } - break; - - case "StageInfoError": - { - mainModel.AddLog("关卡识别错误", "darkred"); - } - break; - - case "PenguinId": - { - var settings = _container.Get(); - if (settings.PenguinId == String.Empty) - { - string id = subTaskDetails["id"].ToString(); - settings.PenguinId = id; - //AsstSetPenguinId(id); - } - } - break; - } - } - - private void procRecruitCalcMsg(JObject details) - { - string what = details["what"].ToString(); - var subTaskDetails = details["details"]; - - var recruitModel = _container.Get(); - - switch (what) - { - case "RecruitTagsDetected": - { - JArray tags = (JArray)subTaskDetails["tags"]; - string info_content = "识别结果: "; - foreach (var tag_name in tags) - { - string tag_str = tag_name.ToString(); - info_content += tag_str + " "; - } - recruitModel.RecruitInfo = info_content; - } - break; - - case "RecruitSpecialTag": - { - string special = subTaskDetails["tag"].ToString(); - using (var toast = new ToastNotification("公招提示")) - { - toast.AppendContentText(special).ShowRecruit(); - } - } - break; - - case "RecruitResult": - { - string resultContent = string.Empty; - JArray result_array = (JArray)subTaskDetails["result"]; - int level = (int)subTaskDetails["level"]; - foreach (var combs in result_array) - { - int tag_level = (int)combs["level"]; - resultContent += tag_level + "星Tags: "; - foreach (var tag in (JArray)combs["tags"]) - { - resultContent += tag.ToString() + " "; - } - resultContent += "\n\t"; - foreach (var oper in (JArray)combs["opers"]) - { - resultContent += oper["level"].ToString() + " - " + oper["name"].ToString() + " "; - } - resultContent += "\n\n"; - } - recruitModel.RecruitResult = resultContent; - if (level >= 5) - { - using (var toast = new ToastNotification($"公招出 {level} 星了哦!")) - { - toast.AppendContentText(new string('★', level)).ShowRecruit(row: 2); - } - } - } - break; - } - } - - public bool AsstConnect() - { - var settings = _container.Get(); - if (settings.AdbPath == String.Empty || - settings.ConnectAddress == String.Empty) - { - return false; - } - else - { - return AsstConnect(_handle, settings.AdbPath, settings.ConnectAddress, settings.ConnectConfig); - } - } - - private bool AsstAppendTaskWithEncoding(string type, JObject task_params = null) - { - task_params = task_params ?? new JObject(); - return AsstAppendTask(_handle, type, JsonConvert.SerializeObject(task_params)) != 0; - } - - public bool AsstAppendFight(string stage, int max_medicine, int max_stone, int max_times) - { - var task_params = new JObject(); - task_params["stage"] = stage; - task_params["medicine"] = max_medicine; - task_params["stone"] = max_stone; - task_params["times"] = max_times; - task_params["report_to_penguin"] = true; - var settings = _container.Get(); - task_params["penguin_id"] = settings.PenguinId; - task_params["server"] = "CN"; - return AsstAppendTaskWithEncoding("Fight", task_params); - } - - public bool AsstAppendAward() - { - return AsstAppendTaskWithEncoding("Award"); - } - - public bool AsstAppendStartUp() - { - return AsstAppendTaskWithEncoding("StartUp"); - } - - public bool AsstAppendVisit() - { - return AsstAppendTaskWithEncoding("Visit"); - } - - public bool AsstAppendMall(bool with_shopping, string[] firstlist, string[] blacklist) - { - var task_params = new JObject(); - task_params["shopping"] = with_shopping; - task_params["buy_first"] = new JArray { firstlist }; - task_params["blacklist"] = new JArray { blacklist }; - return AsstAppendTaskWithEncoding("Mall", task_params); - } - - public bool AsstAppendRecruit(int max_times, int[] select_level, int required_len, int[] confirm_level, int confirm_len, bool need_refresh, bool use_expedited) - { - var task_params = new JObject(); - task_params["refresh"] = need_refresh; - task_params["select"] = new JArray(select_level); - task_params["confirm"] = new JArray(confirm_level); - task_params["times"] = max_times; - task_params["set_time"] = true; - task_params["expedite"] = use_expedited; - task_params["expedite_times"] = max_times; - return AsstAppendTaskWithEncoding("Recruit", task_params); - } - - public bool AsstAppendInfrast(int work_mode, string[] order, int order_len, string uses_of_drones, double dorm_threshold) - { - var task_params = new JObject(); - //task_params["mode"] = 0; - task_params["facility"] = new JArray(order); - task_params["drones"] = uses_of_drones; - task_params["threshold"] = dorm_threshold; - task_params["replenish"] = true; - return AsstAppendTaskWithEncoding("Infrast", task_params); - } - - public bool AsstAppendRoguelike(int mode) - { - var task_params = new JObject(); - task_params["mode"] = mode; - task_params["opers"] = new JArray { - new JObject { { "name", "山" }, { "skill", 2 }, { "skill_usage", 2 } }, - new JObject { { "name", "棘刺" }, { "skill", 3 }, { "skill_usage", 1 } }, - new JObject { { "name", "芙蓉" }, { "skill", 1 }, { "skill_usage", 1 } }, - new JObject { { "name", "梓兰" }, { "skill", 1 }, { "skill_usage", 1 } }, - }; - return AsstAppendTaskWithEncoding("Roguelike", task_params); - } - - public bool AsstStartRecruitCalc(int[] select_level, int required_len, bool set_time) - { - var task_params = new JObject(); - task_params["refresh"] = false; - task_params["select"] = new JArray(select_level); - task_params["confirm"] = new JArray(); - task_params["times"] = 0; - task_params["set_time"] = true; - task_params["expedite"] = false; - task_params["expedite_times"] = 0; - return AsstAppendTaskWithEncoding("Recruit", task_params); - } - - public bool AsstStart() - { - return AsstStart(_handle); - } - - public bool AsstStop() - { - return AsstStop(_handle); - } - } - - public enum AsstMsg - { - /* Global Info */ - InternalError = 0, // 内部错误 - InitFailed, // 初始化失败 - ConnectionError, // 连接相关错误 - AllTasksCompleted, // 全部任务完成 - /* TaskChain Info */ - TaskChainError = 10000, // 任务链执行/识别错误 - TaskChainStart, // 任务链开始 - TaskChainCompleted, // 任务链完成 - TaskChainExtraInfo, // 任务链额外信息 - /* SubTask Info */ - SubTaskError = 20000, // 原子任务执行/识别错误 - SubTaskStart, // 原子任务开始 - SubTaskCompleted, // 原子任务完成 - SubTaskExtraInfo // 原子任务额外信息 - }; -} +// MeoAsstGui - A part of the MeoAssistantArknights project +// Copyright (C) 2021 MistEO and Contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY + +using System; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Stylet; +using StyletIoC; + +namespace MeoAsstGui +{ + using AsstHandle = IntPtr; + using TaskId = Int32; + + public class AsstProxy + { + private delegate void CallbackDelegate(int msg, IntPtr json_buffer, IntPtr custom_arg); + + private delegate void ProcCallbckMsg(AsstMsg msg, JObject details); + + [DllImport("MeoAssistant.dll")] private static extern bool AsstLoadResource(byte[] dirname); + + private static bool AsstLoadResource(string dirname) + { + return AsstLoadResource(Encoding.UTF8.GetBytes(dirname)); + } + + [DllImport("MeoAssistant.dll")] private static extern AsstHandle AsstCreate(); + + [DllImport("MeoAssistant.dll")] private static extern AsstHandle AsstCreateEx(CallbackDelegate callback, IntPtr custom_arg); + + [DllImport("MeoAssistant.dll")] private static extern void AsstDestroy(AsstHandle handle); + + [DllImport("MeoAssistant.dll")] private static extern bool AsstConnect(AsstHandle handle, byte[] adb_path, byte[] address, byte[] config); + + private static bool AsstConnect(AsstHandle handle, string adb_path, string address, string config) + { + return AsstConnect(handle, Encoding.UTF8.GetBytes(adb_path), Encoding.UTF8.GetBytes(address), Encoding.UTF8.GetBytes(config)); + } + + [DllImport("MeoAssistant.dll")] private static extern TaskId AsstAppendTask(AsstHandle handle, byte[] type, byte[] task_params); + + private static TaskId AsstAppendTask(AsstHandle handle, string type, string task_params) + { + return AsstAppendTask(handle, Encoding.UTF8.GetBytes(type), Encoding.UTF8.GetBytes(task_params)); + } + + [DllImport("MeoAssistant.dll")] private static extern bool AsstSetTaskParams(AsstHandle handle, TaskId id, byte[] task_params); + + [DllImport("MeoAssistant.dll")] private static extern bool AsstStart(AsstHandle handle); + + [DllImport("MeoAssistant.dll")] private static extern bool AsstStop(AsstHandle handle); + + [DllImport("MeoAssistant.dll")] private static extern void AsstLog(byte[] level, byte[] message); + + private readonly CallbackDelegate _callback; + + public AsstProxy(IContainer container, IWindowManager windowManager) + { + _container = container; + _windowManager = windowManager; + _callback = CallbackFunction; + } + + public void Init() + { + bool loaded = AsstLoadResource(System.IO.Directory.GetCurrentDirectory()); + _handle = AsstCreateEx(_callback, IntPtr.Zero); + + if (loaded == false || _handle == IntPtr.Zero) + { + Execute.OnUIThread(() => + { + _windowManager.ShowMessageBox("出现未知异常", "错误", icon: MessageBoxImage.Error); + Environment.Exit(0); + }); + } + var tvm = _container.Get(); + tvm.Idle = true; + } + + [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true)] + internal static extern int lstrlenA(IntPtr ptr); + + private static string PtrToStringCustom(IntPtr ptr, System.Text.Encoding enc) + { + if (IntPtr.Zero == ptr) + { + return null; + } + if (lstrlenA(ptr) == 0) + { + return string.Empty; + } + int len = lstrlenA(ptr); + Byte[] bytes = new Byte[len + 1]; + Marshal.Copy(ptr, bytes, 0, len + 1); + return enc.GetString(bytes); + } + + private void CallbackFunction(int msg, IntPtr json_buffer, IntPtr custom_arg) + { + string json_str = PtrToStringCustom(json_buffer, System.Text.Encoding.UTF8); + //Console.WriteLine(json_str); + JObject json = (JObject)JsonConvert.DeserializeObject(json_str); + ProcCallbckMsg dlg = new ProcCallbckMsg(procMsg); + Execute.OnUIThread(() => + { + dlg((AsstMsg)msg, json); + }); + } + + private readonly IWindowManager _windowManager; + private readonly IContainer _container; + private IntPtr _handle; + + private void procMsg(AsstMsg msg, JObject details) + { + switch (msg) + { + case AsstMsg.InternalError: + break; + + case AsstMsg.InitFailed: + _windowManager.ShowMessageBox("初始化错误!请检查是否使用了中文路径", "错误", icon: MessageBoxImage.Error); + Environment.Exit(0); + break; + + case AsstMsg.ConnectionError: + break; + + case AsstMsg.AllTasksCompleted: + case AsstMsg.TaskChainError: + case AsstMsg.TaskChainStart: + case AsstMsg.TaskChainCompleted: + case AsstMsg.TaskChainExtraInfo: + procTaskChainMsg(msg, details); + break; + + case AsstMsg.SubTaskError: + case AsstMsg.SubTaskStart: + case AsstMsg.SubTaskCompleted: + case AsstMsg.SubTaskExtraInfo: + procSubTaskMsg(msg, details); + break; + } + } + + private void procTaskChainMsg(AsstMsg msg, JObject details) + { + string taskChain = details["taskchain"].ToString(); + + if (taskChain == "Recruit") + { + if (msg == AsstMsg.TaskChainError) + { + var recruitModel = _container.Get(); + recruitModel.RecruitInfo = "识别错误!"; + } + } + var mainModel = _container.Get(); + + switch (msg) + { + case AsstMsg.TaskChainError: + mainModel.AddLog("任务出错:" + taskChain, "darkred"); + break; + + case AsstMsg.TaskChainStart: + mainModel.AddLog("开始任务:" + taskChain); + break; + + case AsstMsg.TaskChainCompleted: + mainModel.AddLog("完成任务:" + taskChain); + break; + + case AsstMsg.TaskChainExtraInfo: + break; + + case AsstMsg.AllTasksCompleted: + mainModel.Idle = true; + mainModel.AddLog("任务已全部完成"); + mainModel.UseStone = false; + using (var toast = new ToastNotification("任务已全部完成!")) + { + toast.Show(); + } + mainModel.CheckAndShutdown(); + break; + } + } + + private void procSubTaskMsg(AsstMsg msg, JObject details) + { + // 下面几行注释暂时没用到,先注释起来... + //string taskChain = details["taskchain"].ToString(); + //string classType = details["class"].ToString(); + + //var mainModel = _container.Get(); + switch (msg) + { + case AsstMsg.SubTaskError: + procSubTaskError(details); + break; + + case AsstMsg.SubTaskStart: + procSubTaskStart(details); + break; + + case AsstMsg.SubTaskCompleted: + procSubTaskCompleted(details); + break; + + case AsstMsg.SubTaskExtraInfo: + procSubTaskExtraInfo(details); + break; + } + } + + private void procSubTaskError(JObject details) + { + string subTask = details["subtask"].ToString(); + + var mainModel = _container.Get(); + + switch (subTask) + { + case "AutoRecruitTask": + mainModel.AddLog("公招识别错误,已返回", "darkred"); + break; + + //case "StageDropsTask": + // mainModel.AddLog("关卡识别错误", "darkred"); + // break; + + case "ReportToPenguinStats": + mainModel.AddLog("上传企鹅数据错误", "darkred"); + break; + + case "CheckStageValid": + mainModel.AddLog("EX 关卡,已停止", "darkred"); + break; + } + } + + private void procSubTaskStart(JObject details) + { + string subTask = details["subtask"].ToString(); + + var mainModel = _container.Get(); + if (subTask == "ProcessTask") + { + string taskName = details["details"]["task"].ToString(); + int execTimes = (int)details["details"]["exec_times"]; + + switch (taskName) + { + case "StartButton2": + mainModel.AddLog("已开始行动 " + execTimes + " 次", "darkcyan"); + break; + + case "MedicineConfirm": + mainModel.AddLog("已吃药 " + execTimes + " 个", "darkcyan"); + break; + + case "StoneConfirm": + mainModel.AddLog("已碎石 " + execTimes + " 颗", "darkcyan"); + break; + + case "AbandonAction": + mainModel.AddLog("代理指挥失误", "darkred"); + break; + + case "RecruitRefreshConfirm": + mainModel.AddLog("已刷新标签", "darkcyan"); + break; + + case "RecruitConfirm": + mainModel.AddLog("已确认招募", "darkcyan"); + break; + + case "InfrastDormDoubleConfirmButton": + mainModel.AddLog("干员冲突", "darkred"); + break; + + /* 肉鸽相关 */ + case "Roguelike1Start": + mainModel.AddLog("已开始探索 " + execTimes + " 次", "darkcyan"); + break; + + case "Roguelike1StageTraderInvestConfirm": + mainModel.AddLog("已投资 " + execTimes + " 个源石锭", "darkcyan"); + break; + + case "Roguelike1ExitThenAbandon": + mainModel.AddLog("已放弃本次探索"); + break; + + //case "Roguelike1StartAction": + // mainModel.AddLog("开始战斗"); + // break; + + case "Roguelike1MissionCompletedFlag": + mainModel.AddLog("战斗完成"); + break; + + case "Roguelike1MissionFailedFlag": + mainModel.AddLog("战斗失败"); + break; + + case "Roguelike1StageTraderEnter": + mainModel.AddLog("关卡:诡异行商"); + break; + + case "Roguelike1StageSafeHouseEnter": + mainModel.AddLog("关卡:安全的角落"); + break; + + case "Roguelike1StageEncounterEnter": + mainModel.AddLog("关卡:不期而遇/古堡馈赠"); + break; + + //case "Roguelike1StageBoonsEnter": + // mainModel.AddLog("古堡馈赠"); + // break; + + case "Roguelike1StageCambatDpsEnter": + mainModel.AddLog("关卡:普通作战"); + break; + + case "Roguelike1StageEmergencyDps": + mainModel.AddLog("关卡:紧急作战"); + break; + + case "Roguelike1StageDreadfulFoe": + mainModel.AddLog("关卡:险路恶敌"); + break; + + case "Roguelike1StageTraderInvestSystemFull": + mainModel.AddLog("投资达到上限", "darkcyan"); + break; + } + } + } + + private void procSubTaskCompleted(JObject details) + { + } + + private void procSubTaskExtraInfo(JObject details) + { + string taskChain = details["taskchain"].ToString(); + + if (taskChain == "Recruit") + { + procRecruitCalcMsg(details); + } + + string what = details["what"].ToString(); + var subTaskDetails = details["details"]; + + var mainModel = _container.Get(); + switch (what) + { + case "StageDrops": + { + string cur_drops = string.Empty; + JArray drops = (JArray)subTaskDetails["drops"]; + foreach (var item in drops) + { + string itemName = item["itemName"].ToString(); + int count = (int)item["quantity"]; + cur_drops += $"{itemName} : {count}\n"; + } + cur_drops = cur_drops.EndsWith("\n") ? cur_drops.TrimEnd('\n') : "无"; + mainModel.AddLog("当次掉落:\n" + cur_drops); + + string all_drops = string.Empty; + JArray statistics = (JArray)subTaskDetails["stats"]; + foreach (var item in statistics) + { + string itemName = item["itemName"].ToString(); + int count = (int)item["quantity"]; + all_drops += $"{itemName} : {count}\n"; + } + all_drops = all_drops.EndsWith("\n") ? all_drops.TrimEnd('\n') : "无"; + mainModel.AddLog("掉落统计:\n" + all_drops); + } + break; + + case "EnterFacility": + mainModel.AddLog("当前设施:" + subTaskDetails["facility"] + " " + (int)subTaskDetails["index"]); + break; + + case "RecruitTagsDetected": + { + JArray tags = (JArray)subTaskDetails["tags"]; + string log_content = string.Empty; + foreach (var tag_name in tags) + { + string tag_str = tag_name.ToString(); + log_content += tag_str + "\n"; + } + log_content = log_content.EndsWith("\n") ? log_content.TrimEnd('\n') : "错误"; + mainModel.AddLog("公招识别结果:\n" + log_content); + } + break; + + case "RecruitSpecialTag": + { + string special = subTaskDetails["tag"].ToString(); + using (var toast = new ToastNotification("公招提示")) + { + toast.AppendContentText(special).ShowRecruit(); + } + } + break; + + case "RecruitResult": + { + int level = (int)subTaskDetails["level"]; + if (level >= 5) + { + using (var toast = new ToastNotification($"公招出 {level} 星了哦!")) + { + toast.AppendContentText(new string('★', level)).ShowRecruit(row: 2); + } + mainModel.AddLog(level + " 星 Tags", "darkorange", "Bold"); + } + else + { + mainModel.AddLog(level + " 星 Tags", "darkcyan"); + } + } + break; + + case "RecruitTagsSelected": + { + JArray selected = (JArray)subTaskDetails["tags"]; + string selected_log = string.Empty; + foreach (var tag in selected) + { + selected_log += tag.ToString() + "\n"; + } + selected_log = selected_log.EndsWith("\n") ? selected_log.TrimEnd('\n') : "无"; + + mainModel.AddLog("选择 Tags:\n" + selected_log); + } + break; + + case "NotEnoughStaff": + { + mainModel.AddLog("可用干员不足", "darkred"); + } + break; + + /* Roguelike */ + case "StageInfo": + { + mainModel.AddLog("开始战斗:" + subTaskDetails["name"]); + } + break; + + case "StageInfoError": + { + mainModel.AddLog("关卡识别错误", "darkred"); + } + break; + + case "PenguinId": + { + var settings = _container.Get(); + if (settings.PenguinId == String.Empty) + { + string id = subTaskDetails["id"].ToString(); + settings.PenguinId = id; + //AsstSetPenguinId(id); + } + } + break; + } + } + + private void procRecruitCalcMsg(JObject details) + { + string what = details["what"].ToString(); + var subTaskDetails = details["details"]; + + var recruitModel = _container.Get(); + + switch (what) + { + case "RecruitTagsDetected": + { + JArray tags = (JArray)subTaskDetails["tags"]; + string info_content = "识别结果: "; + foreach (var tag_name in tags) + { + string tag_str = tag_name.ToString(); + info_content += tag_str + " "; + } + recruitModel.RecruitInfo = info_content; + } + break; + + case "RecruitSpecialTag": + { + string special = subTaskDetails["tag"].ToString(); + using (var toast = new ToastNotification("公招提示")) + { + toast.AppendContentText(special).ShowRecruit(); + } + } + break; + + case "RecruitResult": + { + string resultContent = string.Empty; + JArray result_array = (JArray)subTaskDetails["result"]; + int level = (int)subTaskDetails["level"]; + foreach (var combs in result_array) + { + int tag_level = (int)combs["level"]; + resultContent += tag_level + "星Tags: "; + foreach (var tag in (JArray)combs["tags"]) + { + resultContent += tag.ToString() + " "; + } + resultContent += "\n\t"; + foreach (var oper in (JArray)combs["opers"]) + { + resultContent += oper["level"].ToString() + " - " + oper["name"].ToString() + " "; + } + resultContent += "\n\n"; + } + recruitModel.RecruitResult = resultContent; + if (level >= 5) + { + using (var toast = new ToastNotification($"公招出 {level} 星了哦!")) + { + toast.AppendContentText(new string('★', level)).ShowRecruit(row: 2); + } + } + } + break; + } + } + + public bool AsstConnect() + { + var settings = _container.Get(); + if (settings.AdbPath == String.Empty || + settings.ConnectAddress == String.Empty) + { + return false; + } + else + { + return AsstConnect(_handle, settings.AdbPath, settings.ConnectAddress, settings.ConnectConfig); + } + } + + private bool AsstAppendTaskWithEncoding(string type, JObject task_params = null) + { + task_params = task_params ?? new JObject(); + return AsstAppendTask(_handle, type, JsonConvert.SerializeObject(task_params)) != 0; + } + + public bool AsstAppendFight(string stage, int max_medicine, int max_stone, int max_times) + { + var task_params = new JObject(); + task_params["stage"] = stage; + task_params["medicine"] = max_medicine; + task_params["stone"] = max_stone; + task_params["times"] = max_times; + task_params["report_to_penguin"] = true; + var settings = _container.Get(); + task_params["penguin_id"] = settings.PenguinId; + task_params["server"] = "CN"; + return AsstAppendTaskWithEncoding("Fight", task_params); + } + + public bool AsstAppendAward() + { + return AsstAppendTaskWithEncoding("Award"); + } + + public bool AsstAppendStartUp() + { + return AsstAppendTaskWithEncoding("StartUp"); + } + + public bool AsstAppendVisit() + { + return AsstAppendTaskWithEncoding("Visit"); + } + + public bool AsstAppendMall(bool with_shopping, string[] firstlist, string[] blacklist) + { + var task_params = new JObject(); + task_params["shopping"] = with_shopping; + task_params["buy_first"] = new JArray { firstlist }; + task_params["blacklist"] = new JArray { blacklist }; + return AsstAppendTaskWithEncoding("Mall", task_params); + } + + public bool AsstAppendRecruit(int max_times, int[] select_level, int required_len, int[] confirm_level, int confirm_len, bool need_refresh, bool use_expedited) + { + var task_params = new JObject(); + task_params["refresh"] = need_refresh; + task_params["select"] = new JArray(select_level); + task_params["confirm"] = new JArray(confirm_level); + task_params["times"] = max_times; + task_params["set_time"] = true; + task_params["expedite"] = use_expedited; + task_params["expedite_times"] = max_times; + return AsstAppendTaskWithEncoding("Recruit", task_params); + } + + public bool AsstAppendInfrast(int work_mode, string[] order, int order_len, string uses_of_drones, double dorm_threshold) + { + var task_params = new JObject(); + //task_params["mode"] = 0; + task_params["facility"] = new JArray(order); + task_params["drones"] = uses_of_drones; + task_params["threshold"] = dorm_threshold; + task_params["replenish"] = true; + return AsstAppendTaskWithEncoding("Infrast", task_params); + } + + public bool AsstAppendRoguelike(int mode) + { + var task_params = new JObject(); + task_params["mode"] = mode; + task_params["opers"] = new JArray { + new JObject { { "name", "山" }, { "skill", 2 }, { "skill_usage", 2 } }, + new JObject { { "name", "棘刺" }, { "skill", 3 }, { "skill_usage", 1 } }, + new JObject { { "name", "芙蓉" }, { "skill", 1 }, { "skill_usage", 1 } }, + new JObject { { "name", "梓兰" }, { "skill", 1 }, { "skill_usage", 1 } }, + }; + return AsstAppendTaskWithEncoding("Roguelike", task_params); + } + + public bool AsstStartRecruitCalc(int[] select_level, int required_len, bool set_time) + { + var task_params = new JObject(); + task_params["refresh"] = false; + task_params["select"] = new JArray(select_level); + task_params["confirm"] = new JArray(); + task_params["times"] = 0; + task_params["set_time"] = true; + task_params["expedite"] = false; + task_params["expedite_times"] = 0; + return AsstAppendTaskWithEncoding("Recruit", task_params); + } + + public bool AsstStart() + { + return AsstStart(_handle); + } + + public bool AsstStop() + { + return AsstStop(_handle); + } + } + + public enum AsstMsg + { + /* Global Info */ + InternalError = 0, // 内部错误 + InitFailed, // 初始化失败 + ConnectionError, // 连接相关错误 + AllTasksCompleted, // 全部任务完成 + /* TaskChain Info */ + TaskChainError = 10000, // 任务链执行/识别错误 + TaskChainStart, // 任务链开始 + TaskChainCompleted, // 任务链完成 + TaskChainExtraInfo, // 任务链额外信息 + /* SubTask Info */ + SubTaskError = 20000, // 原子任务执行/识别错误 + SubTaskStart, // 原子任务开始 + SubTaskCompleted, // 原子任务完成 + SubTaskExtraInfo // 原子任务额外信息 + }; +} diff --git a/src/MeoAsstGui/Helper/ScrollViewerBinding.cs b/src/MeoAsstGui/Helper/ScrollViewerBinding.cs index fe2913ed6b..ef67fdf86e 100644 --- a/src/MeoAsstGui/Helper/ScrollViewerBinding.cs +++ b/src/MeoAsstGui/Helper/ScrollViewerBinding.cs @@ -224,7 +224,6 @@ namespace MeoAsstGui private static void BindRectangleVerticalOffsetList(ScrollViewer scrollViewer) { - if (scrollViewer.GetValue(RectangleVerticalOffsetListBindingProperty) != null) return; @@ -257,6 +256,5 @@ namespace MeoAsstGui } #endregion RectangleVerticalOffsetList attached property - } } diff --git a/src/MeoAsstGui/Helper/ToastNotification.cs b/src/MeoAsstGui/Helper/ToastNotification.cs index 86a4a8d80c..944bdf7964 100644 --- a/src/MeoAsstGui/Helper/ToastNotification.cs +++ b/src/MeoAsstGui/Helper/ToastNotification.cs @@ -88,7 +88,7 @@ namespace MeoAsstGui // 最大显示宽度 NotificationConstants.MaxWidth = 460d; - #endregion + #endregion 初始化 Notification.Wpf 默认静态配置 } /// @@ -130,7 +130,7 @@ namespace MeoAsstGui None } - #endregion + #endregion 通知提示音列表枚举 /// /// 播放通知提示音 @@ -180,19 +180,23 @@ namespace MeoAsstGui } } - #endregion + #endregion 通知提示音 #region 通知按钮设置 #region 通知按钮变量 + // 左边按钮 protected string _buttonLeftText = null; + protected Action _buttonLeftAction = null; // 右边按钮 protected string _buttonRightText = null; + protected Action _buttonRightAction = null; - #endregion + + #endregion 通知按钮变量 /// /// 给通知添加一个在左边的按钮,比如确定按钮,多次设置只会按最后一次设置生效 @@ -220,7 +224,7 @@ namespace MeoAsstGui return this; } - #endregion + #endregion 通知按钮设置 #region 通知显示 @@ -279,7 +283,7 @@ namespace MeoAsstGui return content; } - #endregion + #endregion 通知基本字体样式和内容模板 #region 显示通知方法 @@ -373,9 +377,9 @@ namespace MeoAsstGui notificationContent: content); } - #endregion + #endregion 显示通知方法 - #endregion + #endregion 通知显示 #region 任务栏闪烁 @@ -457,7 +461,7 @@ namespace MeoAsstGui return FlashWindowEx(ref fInfo); } - #endregion + #endregion 任务栏闪烁 /// /// 通知使用完后释放已使用的数据 @@ -472,6 +476,5 @@ namespace MeoAsstGui _buttonLeftText = _buttonRightText = null; _buttonLeftAction = _buttonRightAction = null; } - } } diff --git a/src/MeoAsstGui/Helper/ViewStatusStorage.cs b/src/MeoAsstGui/Helper/ViewStatusStorage.cs index eb7ae2a96c..37afa53517 100644 --- a/src/MeoAsstGui/Helper/ViewStatusStorage.cs +++ b/src/MeoAsstGui/Helper/ViewStatusStorage.cs @@ -1,84 +1,84 @@ -// MeoAsstGui - A part of the MeoAssistantArknights project -// Copyright (C) 2021 MistEO and Contributors -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY - -using System; -using System.IO; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace MeoAsstGui -{ - // 界面设置存储(读写json文件) - public class ViewStatusStorage - { - private static readonly string _configFilename = System.Environment.CurrentDirectory + "\\gui.json"; - private static JObject _viewStatus = new JObject(); - - public static string Get(string key, string defalut_value) - { - if (_viewStatus.ContainsKey(key)) - { - return _viewStatus[key].ToString(); - } - else - { - return defalut_value; - } - } - - public static void Set(string key, string value) - { - _viewStatus[key] = value; - Save(); - } - - public static bool Load() - { - if (File.Exists(_configFilename)) - { - try - { - string jsonStr = File.ReadAllText(_configFilename); - - // 文件存在但为空,会读出来一个null,感觉c#这库有bug,如果是null 就赋值一个空JObject - _viewStatus = (JObject)JsonConvert.DeserializeObject(jsonStr) ?? new JObject(); - } - catch (Exception) - { - _viewStatus = new JObject(); - return false; - } - } - else - { - _viewStatus = new JObject(); - return false; - } - return true; - } - - public static bool Save() - { - try - { - using (StreamWriter sw = new StreamWriter(_configFilename)) - { - sw.Write(_viewStatus.ToString()); - } - } - catch (Exception) - { - return false; - } - return true; - } - } -} +// MeoAsstGui - A part of the MeoAssistantArknights project +// Copyright (C) 2021 MistEO and Contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY + +using System; +using System.IO; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace MeoAsstGui +{ + // 界面设置存储(读写json文件) + public class ViewStatusStorage + { + private static readonly string _configFilename = System.Environment.CurrentDirectory + "\\gui.json"; + private static JObject _viewStatus = new JObject(); + + public static string Get(string key, string defalut_value) + { + if (_viewStatus.ContainsKey(key)) + { + return _viewStatus[key].ToString(); + } + else + { + return defalut_value; + } + } + + public static void Set(string key, string value) + { + _viewStatus[key] = value; + Save(); + } + + public static bool Load() + { + if (File.Exists(_configFilename)) + { + try + { + string jsonStr = File.ReadAllText(_configFilename); + + // 文件存在但为空,会读出来一个null,感觉c#这库有bug,如果是null 就赋值一个空JObject + _viewStatus = (JObject)JsonConvert.DeserializeObject(jsonStr) ?? new JObject(); + } + catch (Exception) + { + _viewStatus = new JObject(); + return false; + } + } + else + { + _viewStatus = new JObject(); + return false; + } + return true; + } + + public static bool Save() + { + try + { + using (StreamWriter sw = new StreamWriter(_configFilename)) + { + sw.Write(_viewStatus.ToString()); + } + } + catch (Exception) + { + return false; + } + return true; + } + } +} diff --git a/src/MeoAsstGui/UserControl/ToastSettingsUserControl.xaml b/src/MeoAsstGui/UserControl/ToastSettingsUserControl.xaml index b4bff8d5cc..d01a5d5c0b 100644 --- a/src/MeoAsstGui/UserControl/ToastSettingsUserControl.xaml +++ b/src/MeoAsstGui/UserControl/ToastSettingsUserControl.xaml @@ -86,7 +86,6 @@ VerticalAlignment="Bottom" Content="↘ 右下" IsChecked="{Binding ToastPositionBottomRight}" /> -