Compare commits

...

59 Commits

Author SHA1 Message Date
MistEO
c7b80b4603 support to MuMu (not MuMuAsst) 2021-07-18 15:19:15 +08:00
MistEO
1a0add784d try to supoort MuMu 2021-07-18 02:40:57 +08:00
MistEO
70544e7809 update delayTime 2021-07-17 20:12:55 +08:00
MistEO
3430be908b fixed bugs 2021-07-17 20:07:25 +08:00
MistEO
a617f254ff update counting bug 2021-07-17 11:25:47 +08:00
MistEO
028f1ff182 Merge branch 'master' of https://github.com/MistEO/MeoAssistance 2021-07-17 01:06:59 +08:00
MistEO
41a3695556 fixed a filename typo 2021-07-17 01:06:50 +08:00
MistEO
9521285376 Update README.md 2021-07-17 00:47:39 +08:00
MistEO
48125e241b update readme 2021-07-17 00:43:31 +08:00
MistEO
91dad862f8 update gui and readme 2021-07-17 00:35:55 +08:00
MistEO
ff01ce3af4 update configer interface and GUI 2021-07-17 00:03:21 +08:00
MistEO
b701a7ad99 udpate configer 2021-07-16 23:01:40 +08:00
MistEO
96200d5ca6 update gui project 2021-07-16 21:09:57 +08:00
MistEO
0a89b1b48a merge remote 2021-07-16 20:49:26 +08:00
MistEO
11fa36aaaf support Visit Ins 2021-07-16 20:45:02 +08:00
MistEO
78ad680067 update task max_times 2021-07-16 17:51:59 +08:00
MistEO
30cea829f3 add GUI 2021-07-16 07:16:48 +08:00
MistEO
38bff9a43a Merge branch 'master' of https://github.com/MistEO/MeoAssistance 2021-07-15 00:04:25 +08:00
MistEO
f2e73a586d update config 2021-07-15 00:04:10 +08:00
MistEO
694dbcc02b Update README.md 2021-07-14 23:44:21 +08:00
MistEO
bbdb1ce349 update readme 2021-07-14 23:37:57 +08:00
MistEO
e684a1339a update release project 2021-07-14 23:32:05 +08:00
MistEO
d17078e7b8 update UsePtrs 2021-07-14 22:33:57 +08:00
MistEO
db65d51e37 update MoveWindow 2021-07-14 22:29:06 +08:00
MistEO
43848c1e89 support to click UsePrts 2021-07-14 22:28:54 +08:00
MistEO
ae9b6a1265 fixed an error of the cache value 2021-07-14 22:10:08 +08:00
MistEO
b69e7c76e6 update readme 2021-07-14 21:08:52 +08:00
MistEO
e81421579d add cache function to ider 2021-07-14 20:59:36 +08:00
MistEO
1d3c3874ce add config file to vcxproj 2021-07-14 19:58:32 +08:00
MistEO
bfd21e4631 update debugtrace and config 2021-07-14 19:09:48 +08:00
MistEO
27dd02f4f4 update tasks and config 2021-07-14 17:26:36 +08:00
MistEO
30d714b814 update submodule meojson 2021-07-14 15:23:09 +08:00
MistEO
96793ff73a support empty handle class name 2021-07-14 12:44:41 +08:00
MistEO
e591283dea udpate typos and add log 2021-07-14 12:33:47 +08:00
MistEO
c7ac3f0886 update Readme 2021-07-14 00:45:56 +08:00
MistEO
f6a451b3bf support PTRS error 2021-07-13 23:52:10 +08:00
MistEO
92a531b43a add show and hide window function 2021-07-13 23:10:32 +08:00
MistEO
3a4d2e430d support more simulator 2021-07-13 23:10:15 +08:00
MistEO
6a6302cb93 Merge branch 'develop' 2021-07-13 21:30:02 +08:00
MistEO
2454844735 support wide char handle name 2021-07-13 21:29:45 +08:00
MistEO
fba51db8c8 update handle configer 2021-07-13 16:58:21 +08:00
MistEO
06e8a5e6b8 Merge pull request #1 from MistEO/develop
Develop
2021-07-13 01:14:57 +08:00
MistEO
20e5d32d1a update algorithm and configer 2021-07-13 01:02:37 +08:00
MistEO
0169e2c68d rename namespace asst 2021-07-12 20:32:35 +08:00
MistEO
dba404f33b optimze thread 2021-07-12 20:11:10 +08:00
MistEO
839c97c6cd rename Test to Sanity 2021-07-12 19:56:29 +08:00
MistEO
d31b42fd93 update debugprint 2021-07-12 19:35:38 +08:00
MistEO
c52069d59f Merge branch 'develop' 2021-07-12 19:17:37 +08:00
MistEO
8dd30d406a add *.filters 2021-07-12 19:15:49 +08:00
MistEO
af5fcf53ad update tasks queue. add DebugTrace function 2021-07-12 17:44:15 +08:00
MistEO
102ee1cb5c support to use medicine 2021-07-12 01:22:47 +08:00
MistEO
ba9176af93 update reamde 2021-07-11 23:46:55 +08:00
MistEO
f46e2945dc update reamde 2021-07-11 23:44:37 +08:00
MistEO
22cb7ba745 update release 2021-07-11 22:52:09 +08:00
MistEO
e8d91d3e96 update readme ver_alpha_1 2021-07-11 22:35:58 +08:00
MistEO
b2b4daeeed update scale and resource 2021-07-11 22:19:11 +08:00
MistEO
4090400fa4 update vs solution 2021-07-11 21:00:34 +08:00
MistEO
0937be8c02 fix resizeWindow 2021-07-11 18:49:45 +08:00
MistEO
6b216b0cac add configer function, update identification 2021-07-11 07:44:19 +08:00
59 changed files with 3060 additions and 532 deletions

390
.gitignore vendored
View File

@@ -34,6 +34,394 @@
Debug
Release
.vs
*.vcxproj.filters
*.vcxproj.user
*.swp
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Nuget personal access tokens and Credentials
nuget.config
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
.idea/
*.sln.iml

View File

@@ -10,30 +10,70 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeoAssistance", "MeoAssista
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmeojson", "meojson\test\vsproj\meojson\libmeojson\libmeojson.vcxproj", "{9CC7838E-D5FB-4771-848D-5F83D638C5AD}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sanity", "Tools\Sanity\Sanity.vcxproj", "{36BC08F3-71CF-429A-AE69-291BE8962CB2}"
ProjectSection(ProjectDependencies) = postProject
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
{9CC7838E-D5FB-4771-848D-5F83D638C5AD} = {9CC7838E-D5FB-4771-848D-5F83D638C5AD}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MeoAsstGui", "MeoAsstGui\MeoAsstGui.csproj", "{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}"
ProjectSection(ProjectDependencies) = postProject
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
{9CC7838E-D5FB-4771-848D-5F83D638C5AD} = {9CC7838E-D5FB-4771-848D-5F83D638C5AD}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|Any CPU.ActiveCfg = Debug|Win32
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|x64.ActiveCfg = Debug|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|x64.Build.0 = Debug|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|x86.ActiveCfg = Debug|Win32
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|x86.Build.0 = Debug|Win32
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|Any CPU.ActiveCfg = Release|Win32
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.ActiveCfg = Release|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.Build.0 = Release|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x86.ActiveCfg = Release|Win32
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x86.Build.0 = Release|Win32
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Debug|Any CPU.ActiveCfg = Debug|Win32
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Debug|x64.ActiveCfg = Debug|x64
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Debug|x64.Build.0 = Debug|x64
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Debug|x86.ActiveCfg = Debug|Win32
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Debug|x86.Build.0 = Debug|Win32
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Release|Any CPU.ActiveCfg = Release|Win32
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Release|x64.ActiveCfg = Release|x64
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Release|x64.Build.0 = Release|x64
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Release|x86.ActiveCfg = Release|Win32
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Release|x86.Build.0 = Release|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Debug|Any CPU.ActiveCfg = Debug|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Debug|x64.ActiveCfg = Debug|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Debug|x64.Build.0 = Debug|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Debug|x86.ActiveCfg = Debug|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Debug|x86.Build.0 = Debug|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|Any CPU.ActiveCfg = Release|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|x64.ActiveCfg = Release|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|x64.Build.0 = Release|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|x86.ActiveCfg = Release|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|x86.Build.0 = Release|Win32
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|x64.ActiveCfg = Debug|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|x64.Build.0 = Debug|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|x86.ActiveCfg = Debug|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|x86.Build.0 = Debug|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|Any CPU.Build.0 = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.ActiveCfg = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.Build.0 = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x86.ActiveCfg = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -1,36 +0,0 @@
#pragma once
namespace MeoAssistance {
enum class SimulatorType
{
BlueStacks = 0x100
};
enum class HandleType
{
View = 1,
Control = 2,
Window = 4,
BlueStacksView = 0x100 | 1,
BlueStacksControl = 0x100 | 2,
BlueStacksWindow = 0x100 | 4
};
struct Point
{
Point(int x, int y) : x(x), y(y) {}
int x = 0;
int y = 0;
};
struct Rect
{
Rect(int x, int y, int width, int height)
: x(x), y(y), width(width), height(height) {}
Rect operator*(double rhs) const { return { x, y, static_cast<int>(width * rhs), static_cast<int>(height * rhs) }; }
int x = 0;
int y = 0;
int width = 0;
int height = 0;
};
}

View File

@@ -1,110 +0,0 @@
#include "Assistance.h"
#include "WinMacro.h"
using namespace MeoAssistance;
Assistance::Assistance()
: m_control_thread(control_function, this),
m_identify_thread(identify_function, this)
{
}
Assistance::~Assistance()
{
m_control_exit = true;
m_control_running = false;
m_control_cv.notify_all();
m_identify_exit = true;
m_identify_running = false;
m_identify_cv.notify_all();
if (m_control_thread.joinable()) {
m_control_thread.join();
}
if (m_identify_thread.joinable()) {
m_identify_thread.join();
}
}
bool Assistance::setSimulatorType(SimulatorType type)
{
stop();
std::unique_lock<std::mutex> lock(m_tasks_mutex);
std::queue<Task> empty;
m_tasks.swap(empty);
int int_type = static_cast<int>(type);
m_pCtrl = std::make_shared<WinMacro>(static_cast<HandleType>(int_type | static_cast<int>(HandleType::Control)));
m_pWindow = std::make_shared<WinMacro>(static_cast<HandleType>(int_type | static_cast<int>(HandleType::Window)));
m_pView = std::make_shared<WinMacro>(static_cast<HandleType>(int_type | static_cast<int>(HandleType::View)));
return m_pCtrl->findHandle() && m_pWindow->findHandle() && m_pView->findHandle();
}
void Assistance::start()
{
std::unique_lock<std::mutex> lock(m_tasks_mutex);
m_control_running = true;
m_identify_running = true;
m_control_cv.notify_all();
m_identify_cv.notify_all();
}
void Assistance::stop()
{
std::unique_lock<std::mutex> lock(m_tasks_mutex);
m_control_running = false;
m_identify_running = false;
}
void Assistance::identify_function(Assistance* pThis)
{
while (!pThis->m_identify_exit) {
std::unique_lock<std::mutex> lock(pThis->m_tasks_mutex);
if (pThis->m_identify_running) {
pThis->m_pView->getImage(pThis->m_pView->getWindowRect());
pThis->m_tasks.emplace(Task::StartButton1);
pThis->m_control_cv.notify_all();
pThis->m_identify_cv.wait_for(lock, std::chrono::milliseconds(3000));
}
else {
pThis->m_identify_cv.wait(lock);
}
}
}
void Assistance::control_function(Assistance* pThis)
{
pThis->m_pWindow->resizeWindow(1200, 720);
while (!pThis->m_control_exit) {
std::unique_lock<std::mutex> lock(pThis->m_tasks_mutex);
if (pThis->m_control_running && !pThis->m_tasks.empty()) {
const Task task = pThis->m_tasks.front();
pThis->m_tasks.pop();
lock.unlock();
pThis->run_task(task);
}
else {
pThis->m_control_cv.wait(lock);
}
}
}
bool Assistance::run_task(Task task)
{
switch (task)
{
case MeoAssistance::Assistance::Task::StartButton1:
return m_pCtrl->click({ 1060, 600 });
break;
case MeoAssistance::Assistance::Task::StartButton2:
break;
default:
break;
}
}

View File

@@ -1,52 +0,0 @@
#pragma once
#include <thread>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <queue>
#include "AssDef.h"
namespace MeoAssistance {
class WinMacro;
class Assistance
{
enum class Task {
StartButton1,
StartButton2
};
public:
Assistance();
~Assistance();
bool setSimulatorType(SimulatorType type);
void start();
// void pause();
void stop();
private:
static void identify_function(Assistance* pThis); // 识别线程,生产者
static void control_function(Assistance* pThis); // 控制线程,消费者
bool run_task(Task task);
std::shared_ptr<WinMacro> m_pCtrl = nullptr;
std::shared_ptr<WinMacro> m_pWindow = nullptr;
std::shared_ptr<WinMacro> m_pView = nullptr;
std::queue<Task> m_tasks;
std::mutex m_tasks_mutex;
std::thread m_control_thread;
std::thread m_identify_thread;
bool m_control_exit = false;
bool m_identify_exit = false;
bool m_control_running = false;
bool m_identify_running = false;
std::condition_variable m_control_cv;
std::condition_variable m_identify_cv;
};
}

View File

@@ -1,32 +0,0 @@
#include "Identify.h"
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>
using namespace MeoAssistance;
using namespace cv;
double Identify::imgHistComp(const cv::Mat& lhs, const cv::Mat& rhs)
{
cv::Mat lhs_hsv;
cv::Mat rhs_hsv;
cvtColor(lhs, lhs_hsv, COLOR_BGR2HSV);
cvtColor(rhs, rhs_hsv, COLOR_BGR2HSV);
int histSize[] = { 50, 60 };
float h_ranges[] = { 0, 180 };
float s_ranges[] = { 0, 256 };
const float* ranges[] = { h_ranges, s_ranges };
int channels[] = { 0, 1 };
MatND lhs_hist;
MatND rhs_hist;
calcHist(&lhs_hsv, 1, channels, Mat(), lhs_hist, 2, histSize, ranges);
normalize(lhs_hist, lhs_hist, 0, 1, NORM_MINMAX);
calcHist(&rhs_hsv, 1, channels, Mat(), rhs_hist, 2, histSize, ranges);
normalize(rhs_hist, rhs_hist, 0, 1, NORM_MINMAX);
return compareHist(lhs_hist, rhs_hist, CV_COMP_CORREL);
}

View File

@@ -1,17 +0,0 @@
#pragma once
#include <opencv2/opencv.hpp>
namespace MeoAssistance {
class WinMacro;
class Identify
{
public:
Identify() = default;
~Identify() = default;
double imgHistComp(const cv::Mat& lhs, const cv::Mat& rhs);
private:
};
}

View File

@@ -18,6 +18,24 @@
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\Assistance.h" />
<ClInclude Include="include\AsstCaller.h" />
<ClInclude Include="include\AsstDef.h" />
<ClInclude Include="include\Configer.h" />
<ClInclude Include="include\Identify.h" />
<ClInclude Include="include\WinMacro.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Assistance.cpp" />
<ClCompile Include="src\AsstCaller.cpp" />
<ClCompile Include="src\Configer.cpp" />
<ClCompile Include="src\Identify.cpp" />
<ClCompile Include="src\WinMacro.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="..\resource\config.json" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
@@ -40,13 +58,13 @@
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
@@ -78,13 +96,13 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(OPENCV_PATH)\include\opencv2;$(OPENCV_PATH)\include;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)meojson\test\vsproj\meojson\x64\Debug;$(OPENCV_PATH)\x64\vc15\lib;$(LibraryPath)</LibraryPath>
<IncludePath>$(ProjectDir)include;$(SolutionDir)meojson\include;$(OPENCV_PATH)\include;$(IncludePath)</IncludePath>
<LibraryPath>$(TargetDir);$(OPENCV_PATH)\x64\vc15\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(OPENCV_PATH)\include\opencv2;$(OPENCV_PATH)\include;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)meojson\test\vsproj\meojson\x64\Release;$(OPENCV_PATH)\x64\vc15\lib;$(LibraryPath)</LibraryPath>
<IncludePath>$(ProjectDir)include;$(SolutionDir)meojson\include;$(OPENCV_PATH)\include;$(IncludePath)</IncludePath>
<LibraryPath>$(TargetDir);$(OPENCV_NEW_BUILD)lib\Release;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -122,12 +140,25 @@
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>opencv_world452d.lib;libmeojson.lib;%(AdditionalDependencies)</AdditionalDependencies>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
<AdditionalLibraryDirectories>$(TargetDir)</AdditionalLibraryDirectories>
</Link>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
<PostBuildEvent>
<Command>xcopy /e /y /i $(SolutionDir)resource $(TargetDir)resource</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>copy resource</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
@@ -138,28 +169,35 @@
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>opencv_world452.lib;libmeojson.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>opencv_core452.lib;opencv_imgcodecs452.lib;opencv_imgproc452.lib;libmeojson.lib;%(AdditionalDependencies)</AdditionalDependencies>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
<AdditionalLibraryDirectories>$(TargetDir)</AdditionalLibraryDirectories>
</Link>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
<PostBuildEvent>
<Command>xcopy /e /y /i $(SolutionDir)resource $(TargetDir)resource</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>copy resource</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="AssDef.h" />
<ClInclude Include="Assistance.h" />
<ClInclude Include="Identify.h" />
<ClInclude Include="WinMacro.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Assistance.cpp" />
<ClCompile Include="Identify.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="WinMacro.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties _1_1_4resource_4config_1json__JsonSchema="https://beaujs.com/schema.json" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\Configer.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="include\Identify.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="include\WinMacro.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="include\AsstDef.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="include\Assistance.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="include\AsstCaller.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Configer.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\Identify.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\WinMacro.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\Assistance.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\AsstCaller.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\resource\config.json">
<Filter>资源文件</Filter>
</None>
</ItemGroup>
</Project>

View File

@@ -1,207 +0,0 @@
#include "WinMacro.h"
#include <vector>
#include <utility>
#include <ctime>
#include <cassert>
#include <algorithm>
#include <stdint.h>
#include <WinUser.h>
#include <iostream>
using namespace MeoAssistance;
WinMacro::WinMacro(HandleType type)
: m_handle_type(type),
m_rand_engine(time(NULL))
{
}
bool WinMacro::findHandle()
{
switch (m_handle_type) {
case HandleType::BlueStacksControl: {
HWND temp_handle = ::FindWindow(L"BS2CHINAUI", L"BlueStacks App Player");
temp_handle = ::FindWindowEx(temp_handle, NULL, L"BS2CHINAUI", L"HOSTWND");
m_handle = ::FindWindowEx(temp_handle, NULL, L"WindowsForms10.Window.8.app.0.34f5582_r6_ad1", L"BlueStacks Android PluginAndroid");
} break;
case HandleType::BlueStacksView:
case HandleType::BlueStacksWindow:
m_handle = ::FindWindow(L"BS2CHINAUI", L"BlueStacks App Player");
break;
default:
std::cerr << "handle type error! " << static_cast<int>(m_handle_type) << std::endl;
break;
}
#ifdef _DEBUG
std::cout << "type: " << static_cast<int>(m_handle_type) << ", handle: " << m_handle << std::endl;
#endif
if (m_handle != NULL) {
return true;
}
else {
return false;
}
}
bool WinMacro::resizeWindow(int width, int height)
{
if (!(static_cast<int>(m_handle_type) & static_cast<int>(HandleType::Window))) {
return false;
}
return ::MoveWindow(m_handle, 0, 0, width, height, true);
}
double WinMacro::getScreenScale()
{
// 获取窗口当前显示的监视器
// 使用桌面的句柄.
HWND hWnd = GetDesktopWindow();
HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
// 获取监视器逻辑宽度与高度
MONITORINFOEX miex;
miex.cbSize = sizeof(miex);
GetMonitorInfo(hMonitor, &miex);
int cxLogical = (miex.rcMonitor.right - miex.rcMonitor.left);
int cyLogical = (miex.rcMonitor.bottom - miex.rcMonitor.top);
// 获取监视器物理宽度与高度
DEVMODE dm;
dm.dmSize = sizeof(dm);
dm.dmDriverExtra = 0;
EnumDisplaySettings(miex.szDevice, ENUM_CURRENT_SETTINGS, &dm);
int cxPhysical = dm.dmPelsWidth;
int cyPhysical = dm.dmPelsHeight;
// 考虑状态栏大小,逻辑尺寸会比实际小
double horzScale = ((double)cxPhysical / (double)cxLogical);
double vertScale = ((double)cyPhysical / (double)cyLogical);
// 考虑状态栏大小,选择里面大的那个
return std::max(horzScale, vertScale);
}
bool WinMacro::click(Point p)
{
if (!(static_cast<int>(m_handle_type) & static_cast<int>(HandleType::Control))) {
return false;
}
#ifdef _DEBUG
std::cout << "click: " << p.x << ", " << p.y << std::endl;
#endif
LPARAM lparam = MAKELPARAM(p.x, p.y);
::SendMessage(m_handle, WM_LBUTTONDOWN, MK_LBUTTON, lparam);
::SendMessage(m_handle, WM_LBUTTONUP, 0, lparam);
return true;
}
bool WinMacro::clickRange(Rect rect)
{
if (!(static_cast<int>(m_handle_type) & static_cast<int>(HandleType::Control))) {
return false;
}
int x = 0, y = 0;
if (rect.width == 0) {
x = rect.x;
}
else {
std::poisson_distribution<int> x_rand(rect.width);
x = x_rand(m_rand_engine) + rect.x;
}
if (rect.height == 0) {
y = rect.y;
}
else {
std::poisson_distribution<int> y_rand(rect.height);
int y = y_rand(m_rand_engine) + rect.y;
}
return click({ x, y });
}
Rect WinMacro::getWindowRect()
{
RECT rect;
bool ret = ::GetWindowRect(m_handle, &rect);
if (!ret) {
return { 0, 0, 0 ,0 };
}
double scale = getScreenScale();
return Rect{ rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top } * scale;
}
cv::Mat WinMacro::getImage(Rect rect)
{
if (!(static_cast<int>(m_handle_type) & static_cast<int>(HandleType::View))) {
return cv::Mat();
}
HDC pDC;// 源DC
//判断是不是窗口句柄如果是的话不能使用GetDC来获取DC 不然截图会是黑屏
if (m_handle == ::GetDesktopWindow())
{
pDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
}
else
{
pDC = ::GetDC(m_handle);//获取屏幕DC(0为全屏句柄则为窗口)
}
int BitPerPixel = ::GetDeviceCaps(pDC, BITSPIXEL);//获得颜色模式
if (rect.width == 0 && rect.height == 0)//默认宽度和高度为全屏
{
rect.width = ::GetDeviceCaps(pDC, HORZRES); //设置图像宽度全屏
rect.height = ::GetDeviceCaps(pDC, VERTRES); //设置图像高度全屏
}
HDC memDC;//内存DC
memDC = ::CreateCompatibleDC(pDC);
HBITMAP memBitmap, oldmemBitmap;//建立和屏幕兼容的bitmap
memBitmap = ::CreateCompatibleBitmap(pDC, rect.width, rect.height);
oldmemBitmap = (HBITMAP)::SelectObject(memDC, memBitmap);//将memBitmap选入内存DC
if (m_handle == ::GetDesktopWindow())
{
BitBlt(memDC, 0, 0, rect.width, rect.height, pDC, rect.x, rect.y, SRCCOPY);//图像宽度高度和截取位置
}
else
{
bool bret = ::PrintWindow(m_handle, memDC, PW_CLIENTONLY);
if (!bret)
{
BitBlt(memDC, 0, 0, rect.width, rect.height, pDC, rect.x, rect.y, SRCCOPY);//图像宽度高度和截取位置
}
}
BITMAP bmp;
GetObject(memBitmap, sizeof(BITMAP), &bmp);
int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel / 8;
cv::Mat dst_mat;
dst_mat.create(cv::Size(bmp.bmWidth, bmp.bmHeight), CV_MAKETYPE(CV_8U, nChannels));
GetBitmapBits(memBitmap, bmp.bmHeight * bmp.bmWidth * nChannels, dst_mat.data);
DeleteObject(memBitmap);
DeleteDC(memDC);
ReleaseDC(m_handle, pDC);
#ifdef _DEBUG
// 获取程序当前路径
char curpath[_MAX_PATH] = { 0 };
::GetModuleFileNameA(NULL, curpath, _MAX_PATH);
std::string filename(curpath);
filename = filename.substr(0, filename.find_last_of('\\')) + "\\test.bmp";
cv::imwrite(filename, dst_mat);
#endif
return dst_mat;
}

View File

@@ -1,30 +0,0 @@
#pragma once
#include <string>
#include <random>
#include <Windows.h>
#include <opencv2/opencv.hpp>
#include "AssDef.h"
namespace MeoAssistance {
class WinMacro
{
public:
WinMacro(HandleType type);
~WinMacro() = default;
bool findHandle();
bool resizeWindow(int Width, int Height);
bool click(Point p);
bool clickRange(Rect rect);
cv::Mat getImage(Rect rect);
Rect getWindowRect();
double getScreenScale();
private:
HandleType m_handle_type;
HWND m_handle;
std::minstd_rand m_rand_engine;
};
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include <thread>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <optional>
#include <unordered_map>
#include "AsstDef.h"
namespace asst {
class WinMacro;
class Identify;
class __declspec(dllexport) Assistance
{
public:
Assistance();
~Assistance();
std::optional<std::string> setSimulator(const std::string & simulator_name = std::string());
void start(const std::string & task);
void stop(bool block = true);
bool setParam(const std::string& type, const std::string& param, const std::string& value);
std::optional<std::string> getParam(const std::string& type, const std::string& param);
private:
static void workingProc(Assistance* pThis);
std::shared_ptr<WinMacro> m_pWindow = nullptr;
std::shared_ptr<WinMacro> m_pView = nullptr;
std::shared_ptr<WinMacro> m_pCtrl = nullptr;
std::shared_ptr<Identify> m_pIder = nullptr;
bool m_inited = false;
std::thread m_working_thread;
std::mutex m_mutex;
std::condition_variable m_condvar;
bool m_thread_exit = false;
bool m_thread_running = false;
std::vector<std::string> m_next_tasks;
};
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include "Assistance.h"
#ifdef __cplusplus
extern "C" {
#endif
extern __declspec(dllexport) asst::Assistance* CreateAsst();
extern __declspec(dllexport) void DestoryAsst(asst::Assistance* p_asst);
extern __declspec(dllexport) bool AsstCatchSimulator(asst::Assistance* p_asst);
extern __declspec(dllexport) void AsstStart(asst::Assistance* p_asst, const char* task);
extern __declspec(dllexport) void AsstStop(asst::Assistance* p_asst);
extern __declspec(dllexport) bool AsstSetParam(asst::Assistance* p_asst, const char* type, const char* param, const char* value);
extern __declspec(dllexport) bool AsstGetParam(asst::Assistance* p_asst, const char* type, const char* param, char * buffer, int buffer_size);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,126 @@
#pragma once
#include <mutex>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <process.h>
#include <Windows.h>
namespace asst {
enum class HandleType
{
Window = 1,
View = 2,
Control = 4
};
struct Point
{
Point() = default;
Point(int x, int y) : x(x), y(y) {}
int x = 0;
int y = 0;
};
struct Rect
{
Rect() = default;
Rect(int x, int y, int width, int height)
: x(x), y(y), width(width), height(height) {}
Rect operator*(double rhs) const
{
return { x, y, static_cast<int>(width * rhs), static_cast<int>(height * rhs) };
}
Rect center_zoom(double scale)
{
int half_width_scale = static_cast<int>(width * (1 - scale) / 2);
int half_hight_scale = static_cast<int>(height * (1 - scale) / 2);
return { x + half_width_scale, y + half_hight_scale, width - half_width_scale, height - half_hight_scale };
}
int x = 0;
int y = 0;
int width = 0;
int height = 0;
};
static std::string GetCurrentDir()
{
static std::string cur_dir;
if (cur_dir.empty()) {
char exepath_buff[_MAX_PATH] = { 0 };
::GetModuleFileNameA(NULL, exepath_buff, _MAX_PATH);
std::string exepath(exepath_buff);
cur_dir = exepath.substr(0, exepath.find_last_of('\\') + 1);
}
return cur_dir;
}
static std::string GetResourceDir()
{
static std::string res_dir = GetCurrentDir() + "resource\\";
return res_dir;
}
inline void StreamArgs(std::ostream& os)
{
os << std::endl;
}
template <typename T, typename... Args>
inline void StreamArgs(std::ostream& os, T&& first, Args && ...rest)
{
os << first << " ";
StreamArgs(os, std::forward<Args>(rest)...);
}
template <typename... Args>
void DebugPrint(const std::string& level, Args &&... args)
{
static std::mutex trace_mutex;
std::unique_lock<std::mutex> trace_lock(trace_mutex);
#ifdef _DEBUG
auto & out_stream = std::cout;
#else
std::ofstream out_stream(GetCurrentDir() + "asst.log", std::ios::out | std::ios::app);
#endif
SYSTEMTIME curtime;
GetLocalTime(&curtime);
char buff[64] = { 0 };
sprintf_s(buff, "[%04d-%02d-%02d %02d:%02d:%02d.%03d][%s][Px%x][Tx%x]",
curtime.wYear, curtime.wMonth, curtime.wDay,
curtime.wHour, curtime.wMinute, curtime.wSecond, curtime.wMilliseconds,
level.c_str(), _getpid(), GetCurrentThreadId());
StreamArgs(out_stream, buff, std::forward<Args>(args)...);
}
template <typename... Args>
inline void DebugTrace(Args &&... args)
{
//#ifdef _DEBUG
DebugPrint("TRC", std::forward<Args>(args)...);
//#endif
}
template <typename... Args>
inline void DebugTraceInfo(Args &&... args)
{
DebugPrint("INF", std::forward<Args>(args)...);
}
template <typename... Args>
inline void DebugTraceError(Args &&... args)
{
DebugPrint("ERR", std::forward<Args>(args)...);
}
static std::string replace_all_distinct(const std::string& src, const std::string& old_value, const std::string& new_value)
{
std::string str = src;
for (std::string::size_type pos(0); pos != std::string::npos; pos += new_value.length()) {
if ((pos = str.find(old_value, pos)) != std::string::npos)
str.replace(pos, old_value.length(), new_value);
else
break;
}
return str;
}
}

View File

@@ -0,0 +1,78 @@
#pragma once
#include <string>
#include <unordered_map>
#include <vector>
#include <optional>
#include "AsstDef.h"
namespace asst {
struct HandleInfo {
std::string className;
std::string windowName;
};
struct AdbCmd {
std::string path;
std::string connect;
std::string click;
};
struct SimulatorInfo {
std::vector<HandleInfo> window;
std::vector<HandleInfo> view;
std::vector<HandleInfo> control;
bool is_adb = false;
AdbCmd adb;
int width = 0;
int height = 0;
int x_offset = 0;
int y_offset = 0;
};
enum class TaskType {
ClickSelf,
ClickRand,
DoNothing,
Stop,
ClickRect
};
struct TaskInfo {
std::string filename;
double threshold = 0;
TaskType type;
std::vector<std::string> next;
int exec_times = 0;
int max_times = INT_MAX;
asst::Rect specific_area;
int pre_delay = 0;
int rear_delay = 0;
};
struct Options {
std::string delayType;
int delayFixedTime = 0;
bool cache = false;
};
class Configer
{
public:
~Configer() = default;
static bool reload();
static std::string m_version;
static Options m_options;
static std::unordered_map<std::string, TaskInfo> m_tasks;
static std::unordered_map<std::string, SimulatorInfo> m_handles;
static bool setParam(const std::string& type, const std::string& param, const std::string& value);
static std::optional<std::string> getParam(const std::string& type, const std::string& param);
static void clearExecTimes();
private:
Configer() = default;
static std::string m_curDir;
};
}

View File

@@ -0,0 +1,42 @@
#pragma once
#include "AsstDef.h"
#include <opencv2/opencv.hpp>
#include <unordered_map>
#include <utility>
#include <tuple>
namespace asst {
class WinMacro;
class Identify
{
public:
Identify() = default;
~Identify() = default;
void setUseCache(bool b) noexcept;
bool addImage(const std::string& name, const std::string& path);
// return tuple< algorithmType, suitability, scaled asst::rect>
std::tuple<int, double, asst::Rect> findImage(const cv::Mat& image, const std::string& templ, double threshold = 0.99);
void clear_cache();
private:
cv::Mat image2Hist(const cv::Mat& src);
double imageHistComp(const cv::Mat& src, const cv::MatND& hist);
asst::Rect cvRect2Rect(const cv::Rect& cvRect) {
return asst::Rect(cvRect.x, cvRect.y, cvRect.width, cvRect.height);
}
// return pair< suitability, raw opencv::point>
std::pair<double, cv::Point> findImage(const cv::Mat& cur, const cv::Mat& templ);
std::unordered_map<std::string, cv::Mat> m_mat_map;
bool m_use_cache = true;
std::unordered_map<std::string, std::pair<cv::Rect, cv::Mat>> m_cache_map;
};
}

View File

@@ -0,0 +1,41 @@
#pragma once
#include <string>
#include <random>
#include <Windows.h>
#include <opencv2/opencv.hpp>
#include "AsstDef.h"
namespace asst {
class WinMacro
{
public:
WinMacro(const std::string & simulator_name, HandleType type);
~WinMacro() = default;
bool captured() const noexcept;
bool resizeWindow(int Width, int Height);
bool resizeWindow(); // by configer
bool showWindow();
bool hideWindow();
bool click(const Point & p);
bool clickRange(const Rect & rect);
cv::Mat getImage(const Rect& rect);
Rect getWindowRect();
static double getScreenScale();
private:
bool findHandle();
const std::string m_simulator_name;
const HandleType m_handle_type;
HWND m_handle = NULL;
bool m_is_adb = false;
std::string m_click_cmd;
std::minstd_rand m_rand_engine;
int m_width = 0;
int m_height = 0;
int m_x_offset = 0;
int m_y_offset = 0;
};
}

View File

@@ -1,25 +0,0 @@
#include "Assistance.h"
#include "Identify.h"
#include <iostream>
int main(int argc, char** argv)
{
using namespace MeoAssistance;
Assistance ass;
if (!ass.setSimulatorType(SimulatorType::BlueStacks)) {
std::cerr << "failed" << std::endl;
return -1;
}
std::cout << "start" << std::endl;
ass.start();
getchar();
std::cout << "stop" << std::endl;
ass.stop();
return 0;
}

View File

@@ -0,0 +1,193 @@
#include "Assistance.h"
#include "WinMacro.h"
#include "Configer.h"
#include "Identify.h"
using namespace asst;
Assistance::Assistance()
{
Configer::reload();
m_pIder = std::make_shared<Identify>();
for (auto&& [name, info] : Configer::m_tasks)
{
m_pIder->addImage(name, GetResourceDir() + info.filename);
}
m_pIder->setUseCache(Configer::m_options.cache);
m_working_thread = std::thread(workingProc, this);
}
Assistance::~Assistance()
{
if (m_pWindow != nullptr) {
m_pWindow->showWindow();
}
m_thread_exit = true;
m_thread_running = false;
m_condvar.notify_one();
if (m_working_thread.joinable()) {
m_working_thread.join();
}
}
std::optional<std::string> Assistance::setSimulator(const std::string& simulator_name)
{
stop();
auto create_handles = [&](const std::string& name) -> bool {
m_pWindow = std::make_shared<WinMacro>(name, HandleType::Window);
m_pView = std::make_shared<WinMacro>(name, HandleType::View);
m_pCtrl = std::make_shared<WinMacro>(name, HandleType::Control);
return m_pWindow->captured() && m_pView->captured() && m_pCtrl->captured();
};
bool ret = false;
std::string cor_name = simulator_name;
std::unique_lock<std::mutex> lock(m_mutex);
if (simulator_name.empty()) {
for (auto&& [name, value] : Configer::m_handles)
{
ret = create_handles(name);
if (ret) {
cor_name = name;
break;
}
}
}
else {
ret = create_handles(simulator_name);
}
if (ret && m_pWindow->showWindow() && m_pWindow->resizeWindow() ) {
m_inited = true;
return cor_name;
}
else {
m_inited = false;
return std::nullopt;
}
}
void Assistance::start(const std::string& task)
{
if (m_thread_running || !m_inited) {
return;
}
std::unique_lock<std::mutex> lock(m_mutex);
m_pIder->clear_cache();
m_next_tasks.clear();
m_next_tasks.emplace_back(task);
m_thread_running = true;
m_condvar.notify_one();
}
void Assistance::stop(bool block)
{
std::unique_lock<std::mutex> lock;
if (block) {
lock = std::unique_lock<std::mutex>(m_mutex);
}
m_thread_running = false;
m_next_tasks.clear();
m_pIder->clear_cache();
Configer::clearExecTimes();
}
bool Assistance::setParam(const std::string& type, const std::string& param, const std::string& value)
{
return Configer::setParam(type, param, value);
}
std::optional<std::string> Assistance::getParam(const std::string& type, const std::string& param)
{
return Configer::getParam(type, param);
}
void Assistance::workingProc(Assistance* pThis)
{
while (!pThis->m_thread_exit) {
std::unique_lock<std::mutex> lock(pThis->m_mutex);
if (pThis->m_thread_running) {
auto curImg = pThis->m_pView->getImage(pThis->m_pView->getWindowRect());
std::string matched_task;
Rect matched_rect;
for (auto&& task_name : pThis->m_next_tasks) {
double threshold = Configer::m_tasks[task_name].threshold;
auto&& [algorithm, value, rect] = pThis->m_pIder->findImage(curImg, task_name, threshold);
DebugTrace(task_name, "Type:", algorithm, "Value:", value);
if (algorithm == 0 ||
(algorithm == 1 && value >= threshold)
|| (algorithm == 2 && value >= 0.9998)) {
matched_task = task_name;
matched_rect = rect;
break;
}
}
if (!matched_task.empty()) {
auto && task = Configer::m_tasks[matched_task];
DebugTraceInfo("Matched:", matched_task, "Type:", static_cast<int>(task.type));
if (task.pre_delay > 0) {
DebugTrace("PreDelay", task.pre_delay);
std::this_thread::sleep_for(std::chrono::milliseconds(task.pre_delay));
}
switch (task.type) {
case TaskType::ClickRect:
matched_rect = task.specific_area;
case TaskType::ClickSelf:
if (task.max_times != INT_MAX) {
DebugTrace("CurTimes:", task.exec_times, "MaxTimes:", task.max_times);
}
if (task.exec_times >= task.max_times) {
DebugTraceInfo("Reached limit, Stop.");
pThis->stop(false);
continue;
}
pThis->m_pCtrl->clickRange(matched_rect);
++task.exec_times;
break;
case TaskType::ClickRand:
pThis->m_pCtrl->clickRange(pThis->m_pCtrl->getWindowRect());
break;
case TaskType::DoNothing:
break;
case TaskType::Stop:
DebugTrace("TaskType is Stop");
pThis->stop(false);
continue;
break;
default:
DebugTraceError("Unknown option type:", static_cast<int>(task.type));
break;
}
if (task.rear_delay > 0) {
DebugTrace("RearDelay", task.rear_delay);
std::this_thread::sleep_for(std::chrono::milliseconds(task.rear_delay));
}
pThis->m_next_tasks = Configer::m_tasks[matched_task].next;
std::string nexts_str;
for (auto&& name : pThis->m_next_tasks) {
nexts_str += name + ",";
}
if (nexts_str.back() == ',') {
nexts_str.pop_back();
}
DebugTrace("Next:", nexts_str);
}
pThis->m_condvar.wait_for(lock, std::chrono::milliseconds(Configer::m_options.delayFixedTime));
}
else {
pThis->m_condvar.wait(lock);
}
}
}

View File

@@ -0,0 +1,72 @@
#include "AsstCaller.h"
#include <string.h>
asst::Assistance* CreateAsst()
{
return new asst::Assistance();
}
void DestoryAsst(asst::Assistance* p_asst)
{
if (p_asst == NULL) {
return;
}
delete p_asst;
p_asst = NULL;
}
bool AsstCatchSimulator(asst::Assistance* p_asst)
{
if (p_asst == NULL) {
return false;
}
auto ret = p_asst->setSimulator();
if (ret) {
return true;
}
else {
return false;
}
}
void AsstStart(asst::Assistance* p_asst, const char* task)
{
if (p_asst == NULL) {
}
p_asst->start(task);
}
void AsstStop(asst::Assistance* p_asst)
{
if (p_asst == NULL) {
return;
}
p_asst->stop();
}
bool AsstSetParam(asst::Assistance* p_asst, const char* type, const char* param, const char* value)
{
if (p_asst == NULL) {
return false;
}
return p_asst->setParam(type, param, value);
}
bool AsstGetParam(asst::Assistance* p_asst, const char* type, const char* param, char * buffer, int buffer_size)
{
if (p_asst == NULL) {
return false;
}
auto ret = p_asst->getParam(type, param);
if (!ret) {
return false;
}
strcpy_s(buffer, buffer_size, ret.value().c_str());
return true;
}

View File

@@ -0,0 +1,196 @@
#include "Configer.h"
#include <fstream>
#include <sstream>
#include <algorithm>
#include <Windows.h>
#include "json.h"
#include "AsstDef.h"
using namespace asst;
std::string Configer::m_curDir;
std::string Configer::m_version;
Options Configer::m_options;
std::unordered_map<std::string, TaskInfo> Configer::m_tasks;
std::unordered_map<std::string, SimulatorInfo> Configer::m_handles;
bool Configer::reload()
{
std::string filename = GetResourceDir() + "config.json";
std::ifstream ifs(filename, std::ios::in);
if (!ifs.is_open()) {
return false;
}
std::stringstream iss;
iss << ifs.rdbuf();
ifs.close();
std::string content(iss.str());
auto ret = json::parser::parse(content);
if (!ret) {
return false;
}
auto root = std::move(ret).value();
try {
m_version = root["version"].as_string();
auto options_obj = root["options"].as_object();
m_options.delayType = options_obj["delay"]["type"].as_string();
m_options.delayFixedTime = options_obj["delay"]["fixedTime"].as_integer();
m_options.cache = options_obj["cache"].as_boolean();
auto tasks_obj = root["tasks"].as_object();
for (auto&& [name, task_json] : tasks_obj) {
TaskInfo task_info;
task_info.filename = task_json["filename"].as_string();
task_info.threshold = task_json["threshold"].as_double();
std::string type = task_json["type"].as_string();
std::transform(type.begin(), type.end(), type.begin(), std::tolower);
if (type == "clickself") {
task_info.type = TaskType::ClickSelf;
}
else if (type == "clickrand") {
task_info.type = TaskType::ClickRand;
}
else if (type == "donothing" || type.empty()) {
task_info.type = TaskType::DoNothing;
}
else if (type == "stop") {
task_info.type = TaskType::Stop;
}
else if (type == "clickrect") {
task_info.type = TaskType::ClickRect;
auto area_json = task_json["specificArea"].as_array();
task_info.specific_area = Rect(
area_json[0].as_integer(),
area_json[1].as_integer(),
area_json[2].as_integer(),
area_json[3].as_integer());
}
else {
DebugTraceError("Task:", name, "error:", type);
return false;
}
if (task_json.exist("maxTimes")) {
task_info.max_times = task_json["maxTimes"].as_integer();
}
if (task_json.exist("preDelay")) {
task_info.pre_delay = task_json["preDelay"].as_integer();
}
if (task_json.exist("rearDelay")) {
task_info.rear_delay = task_json["rearDelay"].as_integer();
}
auto next_arr = task_json["next"].as_array();
for (auto&& name : next_arr) {
task_info.next.emplace_back(name.as_string());
}
m_tasks.emplace(name, task_info);
}
auto handle_obj = root["handle"].as_object();
for (auto&& [name, simulator_json] : handle_obj) {
SimulatorInfo simulator_info;
auto window_arr = simulator_json["window"].as_array();
for (auto&& info : window_arr) {
HandleInfo handle_info;
handle_info.className = info["class"].as_string();
handle_info.windowName = info["window"].as_string();
simulator_info.window.emplace_back(handle_info);
}
auto view_arr = simulator_json["view"].as_array();
for (auto&& info : view_arr) {
HandleInfo handle_info;
handle_info.className = info["class"].as_string();
handle_info.windowName = info["window"].as_string();
simulator_info.view.emplace_back(handle_info);
}
auto ctrl_arr = simulator_json["control"].as_array();
for (auto&& info : ctrl_arr) {
HandleInfo handle_info;
handle_info.className = info["class"].as_string();
handle_info.windowName = info["window"].as_string();
simulator_info.control.emplace_back(handle_info);
}
if (simulator_json.exist("adbControl")) {
simulator_info.is_adb = true;
// meojson的bug暂时没空修先转个字符串
simulator_info.adb.path = replace_all_distinct(simulator_json["adbControl"]["path"].as_string(), "\\\\", "\\");
simulator_info.adb.connect = simulator_json["adbControl"]["connect"].as_string();
simulator_info.adb.click = simulator_json["adbControl"]["click"].as_string();
}
simulator_info.width = simulator_json["width"].as_integer();
simulator_info.height = simulator_json["height"].as_integer();
simulator_info.x_offset = simulator_json["xOffset"].as_integer();
simulator_info.y_offset = simulator_json["yOffset"].as_integer();
m_handles.emplace(name, simulator_info);
}
}
catch (json::exception& e) {
DebugTraceError("Load config json error!", e.what());
return false;
}
return true;
}
bool Configer::setParam(const std::string& type, const std::string& param, const std::string& value)
{
if (type == "task.type") {
if (m_tasks.find(param) == m_tasks.cend()) {
return false;
}
auto& task_info = m_tasks[param];
std::string type = value;
std::transform(type.begin(), type.end(), type.begin(), std::tolower);
if (type == "clickself") {
task_info.type = TaskType::ClickSelf;
}
else if (type == "clickrand") {
task_info.type = TaskType::ClickRand;
}
else if (type == "donothing" || type.empty()) {
task_info.type = TaskType::DoNothing;
}
else if (type == "stop") {
task_info.type = TaskType::Stop;
}
else if (type == "clickrect") {
task_info.type = TaskType::ClickRect;
}
else {
DebugTraceError("Task", param, "'s type error:", type);
return false;
}
}
else if (type == "task.maxTimes") {
if (m_tasks.find(param) == m_tasks.cend()) {
return false;
}
m_tasks[param].max_times = std::stoi(value);
}
return true;
}
std::optional<std::string> Configer::getParam(const std::string& type, const std::string& param)
{
if (type == "task.execTimes" && m_tasks.find(param) != m_tasks.cend()) {
return std::to_string(m_tasks.at(param).exec_times);
}
return std::nullopt;
}
void Configer::clearExecTimes()
{
for (auto&& t : m_tasks) {
t.second.exec_times = 0;
}
}

View File

@@ -0,0 +1,108 @@
#include "Identify.h"
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>
using namespace asst;
using namespace cv;
bool Identify::addImage(const std::string& name, const std::string& path)
{
Mat mat = imread(path);
if (mat.empty()) {
return false;
}
m_mat_map.emplace(name, mat);
return true;
}
void Identify::setUseCache(bool b) noexcept
{
if (b) {
m_use_cache = true;
}
else {
m_cache_map.clear();
m_use_cache = false;
}
}
Mat Identify::image2Hist(const cv::Mat& src)
{
Mat src_hsv;
cvtColor(src, src_hsv, COLOR_BGR2HSV);
int histSize[] = { 50, 60 };
float h_ranges[] = { 0, 180 };
float s_ranges[] = { 0, 256 };
const float* ranges[] = { h_ranges, s_ranges };
int channels[] = { 0, 1 };
MatND src_hist;
calcHist(&src_hsv, 1, channels, Mat(), src_hist, 2, histSize, ranges);
normalize(src_hist, src_hist, 0, 1, NORM_MINMAX);
return src_hist;
}
double Identify::imageHistComp(const cv::Mat& src, const cv::MatND& hist)
{
return compareHist(image2Hist(src), hist, CV_COMP_CORREL);
}
std::pair<double, cv::Point> Identify::findImage(const cv::Mat& image, const cv::Mat& templ)
{
Mat image_hsv;
Mat templ_hsv;
cvtColor(image, image_hsv, COLOR_BGR2HSV);
cvtColor(templ, templ_hsv, COLOR_BGR2HSV);
Mat matched;
matchTemplate(image_hsv, templ_hsv, matched, cv::TM_CCORR_NORMED);
double minVal = 0, maxVal = 0;
cv::Point minLoc, maxLoc;
minMaxLoc(matched, &minVal, &maxVal, &minLoc, &maxLoc);
return { maxVal, maxLoc };
}
std::tuple<int, double, asst::Rect> Identify::findImage(const Mat& cur, const std::string& templ, double threshold)
{
if (m_mat_map.find(templ) == m_mat_map.cend()) {
return { 0, 0, asst::Rect() };
}
if (m_use_cache && m_cache_map.find(templ) != m_cache_map.cend()) {
auto&& [rect, hist] = m_cache_map.at(templ);
double value = imageHistComp(cur(rect), hist);
return { 2, value, cvRect2Rect(rect).center_zoom(0.8) };
}
else {
auto&& templ_mat = m_mat_map.at(templ);
auto&& [value, point] = findImage(cur, templ_mat);
cv::Rect raw_rect(point.x, point.y, templ_mat.cols, templ_mat.rows);
if (m_use_cache && value >= threshold) {
m_cache_map.emplace(templ, std::make_pair(raw_rect, image2Hist(cur(raw_rect))));
}
return { 1, value, cvRect2Rect(raw_rect).center_zoom(0.8) };
}
}
void Identify::clear_cache()
{
m_cache_map.clear();
}
/*
std::pair<double, asst::Rect> Identify::findImageWithFile(const cv::Mat& cur, const std::string& filename)
{
Mat mat = imread(filename);
if (mat.empty()) {
return { 0, asst::Rect() };
}
return findImage(cur, mat);
}
*/

View File

@@ -0,0 +1,288 @@
#include "WinMacro.h"
#include <vector>
#include <utility>
#include <ctime>
#include <algorithm>
#include <stdint.h>
#include <WinUser.h>
#include "Configer.h"
#include "AsstDef.h"
using namespace asst;
WinMacro::WinMacro(const std::string& simulator_name, HandleType type)
: m_simulator_name(simulator_name),
m_handle_type(type),
m_rand_engine(time(NULL))
{
findHandle();
}
bool WinMacro::captured() const noexcept
{
return m_handle != NULL;
}
bool WinMacro::findHandle()
{
std::vector<HandleInfo> handle_vec;
auto&& info = Configer::m_handles[m_simulator_name];
switch (m_handle_type) {
case HandleType::Window:
m_width = info.width;
m_height = info.height;
handle_vec = info.window;
break;
case HandleType::View:
handle_vec = info.view;
break;
case HandleType::Control:
m_is_adb = info.is_adb;
m_x_offset = info.x_offset;
m_y_offset = info.y_offset;
handle_vec = info.control;
break;
default:
DebugTraceError("Handle type error!", static_cast<int>(m_handle_type));
return false;
}
m_handle = NULL;
for (auto&& handle_info : handle_vec)
{
wchar_t* class_wbuff = NULL;
if (!handle_info.className.empty()) {
size_t class_len = (handle_info.className.size() + 1) * 2;
class_wbuff = new wchar_t[class_len];
::MultiByteToWideChar(CP_UTF8, 0, handle_info.className.c_str(), -1, class_wbuff, class_len);
}
wchar_t* window_wbuff = NULL;
if (!handle_info.windowName.empty()) {
size_t window_len = (handle_info.windowName.size() + 1) * 2;
window_wbuff = new wchar_t[window_len];
memset(window_wbuff, 0, window_len);
::MultiByteToWideChar(CP_UTF8, 0, handle_info.windowName.c_str(), -1, window_wbuff, window_len);
}
m_handle = ::FindWindowExW(m_handle, NULL, class_wbuff, window_wbuff);
if (class_wbuff != NULL) {
delete[] class_wbuff;
class_wbuff = NULL;
}
if (window_wbuff != NULL) {
delete[] window_wbuff;
window_wbuff = NULL;
}
}
if (m_is_adb && m_handle != NULL) {
DWORD pid = 0;
::GetWindowThreadProcessId(m_handle, &pid);
HANDLE handle = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
LPSTR path_buff = new CHAR[MAX_PATH];
memset(path_buff, 0, MAX_PATH);
DWORD buff_size = MAX_PATH;
QueryFullProcessImageNameA(handle, 0, path_buff, &buff_size);
std::string adb_dir = path_buff;
if (path_buff != NULL) {
delete[] path_buff;
path_buff = NULL;
}
size_t pos = adb_dir.find_last_of('\\') + 1;
adb_dir = adb_dir.substr(0, pos);
adb_dir = '"' + replace_all_distinct(info.adb.path, "[EmulatorPath]", adb_dir) + '"';
std::string connect_cmd = adb_dir + info.adb.connect;
int ret = system(connect_cmd.c_str());
DebugTrace("Call", connect_cmd, "—— ret", ret);
m_click_cmd = adb_dir + info.adb.click;
}
DebugTrace("Handle:", m_handle, "Name:", m_simulator_name, "Type:", static_cast<int>(m_handle_type));
if (m_handle != NULL) {
return true;
}
else {
return false;
}
}
bool WinMacro::resizeWindow(int width, int height)
{
if (m_handle_type != HandleType::Window) {
return false;
}
RECT rect;
bool ret = ::GetWindowRect(m_handle, &rect);
return ret && ::MoveWindow(m_handle, rect.left, rect.top, width / getScreenScale(), height / getScreenScale(), true);
}
bool WinMacro::resizeWindow()
{
return resizeWindow(m_width, m_height);
}
bool WinMacro::showWindow()
{
if (m_handle_type != HandleType::Window) {
return false;
}
return ::ShowWindow(m_handle, SW_RESTORE);
}
bool WinMacro::hideWindow()
{
if (m_handle_type != HandleType::Window) {
return false;
}
return ::ShowWindow(m_handle, SW_HIDE);
}
double WinMacro::getScreenScale()
{
static double scale = 0;
if (scale == 0) {
// 获取窗口当前显示的监视器
// 使用桌面的句柄.
HWND hWnd = GetDesktopWindow();
HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
// 获取监视器逻辑宽度与高度
MONITORINFOEX miex;
miex.cbSize = sizeof(miex);
GetMonitorInfo(hMonitor, &miex);
int cxLogical = (miex.rcMonitor.right - miex.rcMonitor.left);
int cyLogical = (miex.rcMonitor.bottom - miex.rcMonitor.top);
// 获取监视器物理宽度与高度
DEVMODE dm;
dm.dmSize = sizeof(dm);
dm.dmDriverExtra = 0;
EnumDisplaySettings(miex.szDevice, ENUM_CURRENT_SETTINGS, &dm);
int cxPhysical = dm.dmPelsWidth;
int cyPhysical = dm.dmPelsHeight;
// 考虑状态栏大小,逻辑尺寸会比实际小
double horzScale = ((double)cxPhysical / (double)cxLogical);
double vertScale = ((double)cyPhysical / (double)cyLogical);
// 考虑状态栏大小,选择里面大的那个
scale = std::max(horzScale, vertScale);
}
return scale;
}
bool WinMacro::click(const Point& p)
{
if (m_handle_type != HandleType::Control) {
return false;
}
if (m_is_adb) {
int x = (p.x + m_x_offset);
int y = (p.y + m_y_offset);
std::string cur_cmd = replace_all_distinct(m_click_cmd, "[x]", std::to_string(x));
cur_cmd = replace_all_distinct(cur_cmd, "[y]", std::to_string(y));
int ret = system(cur_cmd.c_str());
DebugTrace("Call", cur_cmd, "—— ret", ret);
return !ret;
}
else {
int x = (p.x + m_x_offset) / getScreenScale();
int y = (p.y + m_y_offset) / getScreenScale();
DebugTrace("Click, raw:", p.x, p.y, "cor:", x, y);
LPARAM lparam = MAKELPARAM(x, y);
::SendMessage(m_handle, WM_LBUTTONDOWN, MK_LBUTTON, lparam);
::SendMessage(m_handle, WM_LBUTTONUP, 0, lparam);
return true;
}
}
bool WinMacro::clickRange(const Rect& rect)
{
if (m_handle_type != HandleType::Control) {
return false;
}
int x = 0, y = 0;
if (rect.width == 0) {
x = rect.x;
}
else {
int x_rand = std::poisson_distribution<int>(rect.width / 2)(m_rand_engine);
x = x_rand + rect.x;
}
if (rect.height == 0) {
y = rect.y;
}
else {
int y_rand = std::poisson_distribution<int>(rect.height / 2)(m_rand_engine);
y = y_rand + rect.y;
}
return click({ x, y });
}
Rect WinMacro::getWindowRect()
{
RECT rect;
bool ret = ::GetWindowRect(m_handle, &rect);
if (!ret) {
return Rect();
}
return Rect{ rect.left, rect.top,
static_cast<int>((rect.right - rect.left) * getScreenScale()),
static_cast<int>((rect.bottom - rect.top) * getScreenScale()) };
}
cv::Mat WinMacro::getImage(const Rect& rect)
{
if (m_handle_type != HandleType::View) {
return cv::Mat();
}
HDC pDC;// 源DC
pDC = ::GetDC(m_handle);//获取屏幕DC(0为全屏句柄则为窗口)
int BitPerPixel = ::GetDeviceCaps(pDC, BITSPIXEL);//获得颜色模式
HDC memDC;//内存DC
memDC = ::CreateCompatibleDC(pDC);
HBITMAP memBitmap, oldmemBitmap;//建立和屏幕兼容的bitmap
memBitmap = ::CreateCompatibleBitmap(pDC, rect.width, rect.height);
oldmemBitmap = (HBITMAP)::SelectObject(memDC, memBitmap);//将memBitmap选入内存DC
::PrintWindow(m_handle, memDC, PW_CLIENTONLY);
BITMAP bmp;
GetObject(memBitmap, sizeof(BITMAP), &bmp);
int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel / 8;
cv::Mat dst_mat;
dst_mat.create(cv::Size(bmp.bmWidth, bmp.bmHeight), CV_MAKETYPE(CV_8U, nChannels));
GetBitmapBits(memBitmap, bmp.bmHeight * bmp.bmWidth * nChannels, dst_mat.data);
DeleteObject(memBitmap);
DeleteDC(memDC);
ReleaseDC(m_handle, pDC);
/*
#ifdef _DEBUG
std::string filename = GetCurrentDir() + "\\print.bmp";
cv::imwrite(filename, dst_mat);
#endif
*/
return dst_mat;
}

6
MeoAsstGui/App.config Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>

9
MeoAsstGui/App.xaml Normal file
View File

@@ -0,0 +1,9 @@
<Application x:Class="MeoAsstGui.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MeoAsstGui"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

17
MeoAsstGui/App.xaml.cs Normal file
View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace MeoAsstGui
{
/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : Application
{
}
}

View File

@@ -0,0 +1,20 @@
<Window x:Class="MeoAsstGui.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MeoAsstGui"
mc:Ignorable="d"
Title="MeoAssistance-明日方舟辅助" Height="500" Width="400">
<Grid>
<CheckBox x:Name="checkBox_useMedicine" Content="吃理智药" HorizontalAlignment="Left" Margin="50,100,0,0" VerticalAlignment="Top" Checked="checkBox_useMedicine_Checked" Unchecked="checkBox_useMedicine_Checked" IsChecked="True"/>
<CheckBox x:Name="checkBox_useStone" Content="吃石头" HorizontalAlignment="Left" Margin="50,150,0,0" VerticalAlignment="Top" Checked="checkBox_useStone_Checked" Unchecked="checkBox_useStone_Checked"/>
<TextBox x:Name="textBox_useStone" HorizontalAlignment="Left" Height="23" Margin="112,148,0,0" TextWrapping="Wrap" Text="0" VerticalAlignment="Top" Width="47" TextChanged="textBox_useStone_TextChanged" InputMethod.IsInputMethodEnabled="False"/>
<Label x:Name="label_stoneNumber" Content="颗" HorizontalAlignment="Left" Margin="164,144,0,0" VerticalAlignment="Top" RenderTransformOrigin="-5.771,-6.291"/>
<Button x:Name="button_startSanity" Content="开始刷理智" HorizontalAlignment="Left" Margin="50,200,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_startSanity"/>
<Button x:Name="button_stop" Content="停止" HorizontalAlignment="Left" Margin="50,280,0,0" VerticalAlignment="Top" Width="300" Height="50" Click="button_Click_stop"/>
<Label x:Name="catch_status" Content="" HorizontalAlignment="Left" Margin="50,30,0,0" VerticalAlignment="Top"/>
<Button x:Name="button_visit" Content="访问基建" HorizontalAlignment="Left" Margin="230,200,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_visit"/>
<Label x:Name="exec_times" Content="" HorizontalAlignment="Left" Margin="230,30,0,0" VerticalAlignment="Top"/>
</Grid>
</Window>

View File

@@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.Windows.Threading;
namespace MeoAsstGui
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
[DllImport("MeoAssistance.dll")] static public extern IntPtr CreateAsst();
[DllImport("MeoAssistance.dll")] static public extern void DestoryAsst(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static public extern bool AsstCatchSimulator(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static public extern void AsstStart(IntPtr ptr, string task);
[DllImport("MeoAssistance.dll")] static public extern void AsstStop(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static public extern bool AsstSetParam(IntPtr p_asst, string type, string param, string value);
[DllImport("MeoAssistance.dll")] static public extern bool AsstGetParam(IntPtr p_asst, string type, string param, [In, Out] StringBuilder lp_string, int buffer_size);
private IntPtr p_asst;
private DispatcherTimer update_times = new DispatcherTimer();
public MainWindow()
{
InitializeComponent();
p_asst = CreateAsst();
update_times.Tick += new EventHandler(updateExecTimes);
update_times.Interval = TimeSpan.FromSeconds(1);
}
~MainWindow()
{
DestoryAsst(p_asst);
}
private void button_Click_startSanity(object sender, RoutedEventArgs e)
{
bool catched = AsstCatchSimulator(p_asst);
catch_status.Content = "捕获模拟器窗口:" + catched;
AsstStart(p_asst, "SanityBegin");
update_times.Start();
}
private void button_Click_stop(object sender, RoutedEventArgs e)
{
AsstStop(p_asst);
catch_status.Content = "";
update_times.Stop();
exec_times.Content = "";
}
private void checkBox_useMedicine_Checked(object sender, RoutedEventArgs e)
{
if (checkBox_useMedicine.IsChecked == true)
{
AsstSetParam(p_asst, "task.type", "UseMedicine", "doNothing");
}
else
{
AsstSetParam(p_asst, "task.type", "UseMedicine", "stop");
}
}
private void textBox_useStone_TextChanged(object sender, TextChangedEventArgs e)
{
AsstSetParam(p_asst, "task.maxTimes", "StoneConfirm", textBox_useStone.Text);
}
private void checkBox_useStone_Checked(object sender, RoutedEventArgs e)
{
if (checkBox_useMedicine.IsChecked == true)
{
AsstSetParam(p_asst, "task.type", "UseStone", "doNothing");
}
else
{
AsstSetParam(p_asst, "task.type", "UseStone", "stop");
}
}
private void button_Click_visit(object sender, RoutedEventArgs e)
{
bool catched = AsstCatchSimulator(p_asst);
catch_status.Content = "捕获模拟器窗口:" + catched;
AsstStart(p_asst, "VisitBegin");
}
private void updateExecTimes(object sender, EventArgs e)
{
StringBuilder buff = new StringBuilder(16);
AsstGetParam(p_asst, "task.execTimes", "StartButton2", buff, 16);
exec_times.Content = "已运行 " + buff + " 次";
}
}
}

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>MeoAsstGui</RootNamespace>
<AssemblyName>MeoAsstGui</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.7.2">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.7.2 %28x86 和 x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>xcopy /e /y /i $(SolutionDir)resource $(TargetDir)resource</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("MeoAsstGui")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MeoAsstGui")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
//若要开始生成可本地化的应用程序,请设置
//.csproj 文件中的 <UICulture>CultureYouAreCodingWith</UICulture>
//例如,如果您在源文件中使用的是美国英语,
//使用的是美国英语,请将 <UICulture> 设置为 en-US。 然后取消
//对以下 NeutralResourceLanguage 特性的注释。 更新
//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //主题特定资源词典所处位置
//(未在页面中找到资源时使用,
//或应用程序资源字典中找到时使用)
ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
//(未在页面中找到资源时使用,
//、应用程序或任何主题专用资源字典中找到时使用)
)]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,70 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本: 4.0.30319.42000
//
// 对此文件的更改可能导致不正确的行为,如果
// 重新生成代码,则所做更改将丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace MeoAsstGui.Properties
{
/// <summary>
/// 强类型资源类,用于查找本地化字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// 返回此类使用的缓存 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MeoAsstGui.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 重写当前线程的 CurrentUICulture 属性,对
/// 使用此强类型资源类的所有资源查找执行重写。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,29 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MeoAsstGui.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

117
README.md
View File

@@ -2,6 +2,119 @@
A game assistance for Arknights
一款明日方舟的游戏辅助,目前仅支持蓝叠模拟器
一款明日方舟的游戏辅助,供PC端安卓模拟器使用龟速开发中……
使用C++ WinAPI龟速开发中……
![截图](README/1.png)
## 功能介绍
- 支持自动刷完理智
- 支持自动吃完体力药
- 支持根据设置自动吃石头
- 刷完后程序会自动停止
- 代理失败会自动放弃本次行动
- 支持自动访问好友基建
- 所有操作,都是点击按钮内随机位置,且模拟泊松分布,不会像鼠标宏一样一直是同一个点,没有封号风险
~~(虽然好像也没听说过谁用鼠标宏被封号的)~~
- 模拟器窗口可以被遮挡,即使全屏看视频、玩游戏,也完全不影响辅助运行
~~(但是模拟器还是不能最小化)~~
- 支持多款主流模拟器
- 自适应分辨率及屏幕缩放
- 未来更多功能见[Todo](#Todo)
### 模拟器支持
#### 蓝叠模拟器
完美兼容,作者绝大部分测试均在蓝叠上进行,稳定性最能保障
#### 逍遥模拟器
完美兼容
#### 雷电模拟器
完美兼容,需要收起右侧侧边栏后使用
#### 夜神模拟器
兼容,但辅助开始后不可操作模拟器窗口
#### 腾讯手游助手
兼容但需要手动设置分辨率设置中心——引擎设置——分辨率设置——1280x720——保存后重启模拟器
#### MuMu
MuMu是个奇葩它的所有的窗口句柄均不响应SendMessage鼠标消息
- MuMu模拟器
官方提供了adb控制点击操作的方式本辅助非常勉强的兼容了刷理智的功能需要在模拟器设置里把分辨率设置成1280x720而且效果还不一定能保证。建议使用"Sanity.exe"而不是图形化界面因为adb控制台窗口会一直往出弹
- MuMu手游助手星云引擎
不兼容,可见未来内也想不到什么好主意来兼容的
## 使用说明
### 基本说明
1. 使用支持的模拟器打开明日方舟
2. 解压压缩包,**使用管理员权限**,打开"MeoAsstGui.exe"
3. 注意:运行期间,模拟器窗口可以被遮挡,全屏玩游戏、看视频等,完全不影响,但是!!模拟器不能最小化!!!
### 刷理智
1. 明日方舟打开**蓝色开始按钮**的界面
1. 根据你的需要勾选"吃理智药"和"吃石头"
2. 点击"开始刷理智"
3. 刷完了会自动停止的
### 访问好友基建
1. 明日方舟处于任意界面均可,会自动帮你点过去
2. 点击"访问基建"
3. 达到10次上限或者所有可访问的好友都访问完了就会自动停的
## Todo
~~在做了在做了.jpg~~
- [ ] 功能
- [ ] 图形化界面
- [x] 基本图形化界面
- [ ] 图形化界面进一步完善
- [ ] 日志打印,错误提示
- [ ] 使模拟器窗口不可见的按钮
- [ ] 刷理智
- [x] 支持剿灭
- [x] 支持使模拟器窗口不可见
- [x] 自动吃体力药
- [x] 代理失败的情况
- [x] 支持等级提升
- [x] 支持自动勾选代理指挥
- [ ] 支持刷指定次数
- [x] 自动吃石头(根据设置,指定数量)
- [ ] 支持凌晨4点更新数据
- [ ] 结束界面自动截图,可用于上传企鹅物流
- [ ] 持续监视理智,一有就自动刷掉
- [ ] 模拟器被最小化了,给出提示
- [x] 支持更多模拟器
- [x] 信用访问
- [ ] 基建收菜
- [ ] 当前公招可能干员一览
- [x] 算法
- [x] 更换算法为模板匹配找图,而不是当前的区域相似度对比
- [x] 优化算法效率,添加缓存功能
- [x] 优化任务队列,减少不必要的计算
- [ ] 进一步优化任务队列效率
- [x] 其他
- [x] 尝试减小程序体积
## 致谢
感谢以下开源库/免费API
- WinAPI
- OpenCV
- MeoJson
- WPF

BIN
README/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

161
Tools/Sanity/Sanity.vcxproj Normal file
View File

@@ -0,0 +1,161 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{36bc08f3-71cf-429a-ae69-291be8962cb2}</ProjectGuid>
<RootNamespace>Test</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>Sanity</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)meojson\include;$(SolutionDir)MeoAssistance\include;$(IncludePath)</IncludePath>
<LibraryPath>$(TargetDir);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)meojson\include;$(SolutionDir)MeoAssistance\include;$(IncludePath)</IncludePath>
<LibraryPath>$(TargetDir);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>MeoAssistance.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(TargetDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>MeoAssistance.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(TargetDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>

28
Tools/Sanity/main.cpp Normal file
View File

@@ -0,0 +1,28 @@
#include "Assistance.h"
int main(int argc, char** argv)
{
using namespace asst;
Assistance asst;
auto ret = asst.setSimulator();
if (!ret) {
DebugTraceError("Can't Find Simulator or Permission denied.");
getchar();
return -1;
}
else {
DebugTraceInfo("Find Simulator:", ret.value());
}
DebugTraceInfo("Start");
asst.start("SanityBegin");
getchar();
DebugTraceInfo("Stop");
asst.stop();
return 0;
}

Submodule meojson updated: 0a86b19d2a...d6d07f5e6c

BIN
resource/AbandonAction.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

BIN
resource/Friends.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
resource/FriendsList.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
resource/Loading.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
resource/PRTS.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 KiB

BIN
resource/RationToday.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 KiB

BIN
resource/Return.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
resource/StartButton1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
resource/StartButton2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

BIN
resource/StartToVisit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
resource/UseMedicine.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
resource/UsePrts.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
resource/UseStone.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

BIN
resource/VisitLimited.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
resource/VisitNext.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
resource/VisitNextBlack.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

406
resource/config.json Normal file
View File

@@ -0,0 +1,406 @@
{
"version": "0.3",
"options": {
"delay": {
"type": "fixedTime",
"fixedTime": 1000
},
"cache": true
},
"handle": {
"BlueStacks": {
"window": [
{
"class": "BS2CHINAUI",
"window": "BlueStacks App Player"
}
],
"view": [
{
"class": "BS2CHINAUI",
"window": "BlueStacks App Player"
}
],
"control": [
{
"class": "BS2CHINAUI",
"window": "BlueStacks App Player"
},
{
"class": "BS2CHINAUI",
"window": "HOSTWND"
},
{
"class": "",
"window": "BlueStacks Android PluginAndroid"
}
],
"width": 1294,
"height": 773,
"xOffset": -7,
"yOffset": -47
},
"Nox": {
"window": [
{
"class": "Qt5QWindowIcon",
"window": "夜神模拟器"
}
],
"view": [
{
"class": "Qt5QWindowIcon",
"window": "夜神模拟器"
}
],
"control": [
{
"class": "Qt5QWindowIcon",
"window": "夜神模拟器"
}
],
"width": 1298,
"height": 754,
"xOffset": 0,
"yOffset": -32
},
"LDPlayer": {
"window": [
{
"class": "LDPlayerMainFrame",
"window": "雷电模拟器"
}
],
"view": [
{
"class": "LDPlayerMainFrame",
"window": "雷电模拟器"
}
],
"control": [
{
"class": "LDPlayerMainFrame",
"window": "雷电模拟器"
},
{
"class": "RenderWindow",
"window": "TheRender"
}
],
"width": 1304,
"height": 756,
"xOffset": 0,
"yOffset": -35
},
"XYAZ": {
"window": [
{
"class": "Qt5QWindowIcon",
"window": "逍遥模拟器"
}
],
"view": [
{
"class": "Qt5QWindowIcon",
"window": "逍遥模拟器"
}
],
"control": [
{
"class": "Qt5QWindowIcon",
"window": "逍遥模拟器"
},
{
"class": "Qt5QWindowIcon",
"window": "MainWindowWindow"
}
],
"width": 1282,
"height": 769,
"xOffset": 0,
"yOffset": -47
},
"Tencent": {
"window": [
{
"class": "TXGuiFoundation",
"window": "腾讯手游助手"
}
],
"view": [
{
"class": "TXGuiFoundation",
"window": "腾讯手游助手"
}
],
"control": [
{
"class": "TXGuiFoundation",
"window": "腾讯手游助手"
},
{
"class": "AEngineRenderWindowClass",
"window": "AEngineRenderWindow"
}
],
"width": 1282,
"height": 769,
"xOffset": 0,
"yOffset": -42
},
"MuMuAsst": {
"window": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - 星云引擎"
}
],
"view": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - 星云引擎"
}
],
"control": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - 星云引擎"
}
],
"adbControl": {
"path": "[EmulatorPath]..\\vmonitor\\bin\\adb_server.exe",
"connect": " connect 127.0.0.1:7555",
"click": " shell input tap [x] [y]"
},
"width": 1280,
"height": 809,
"xOffset": 0,
"yOffset": -36
},
"MuMuEmulator": {
"window": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - MuMu模拟器"
}
],
"view": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - MuMu模拟器"
}
],
"control": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - MuMu模拟器"
}
],
"adbControl": {
"path": "[EmulatorPath]..\\vmonitor\\bin\\adb_server.exe",
"connect": " connect 127.0.0.1:7555",
"click": " shell input tap [x] [y]"
},
"width": 1280,
"height": 809,
"xOffset": 0,
"yOffset": -36
}
},
"tasks": {
"SanityBegin": {
"filename": "",
"threshold": 0,
"type": "doNothing",
"next": [
"UsePrts",
"StartButton1",
"StartButton2",
"PRTS",
"UseMedicine",
"UseStone",
"PrtsErrorConfirm",
"Random"
]
},
"UsePrts": {
"filename": "UsePrts.png",
"threshold": 0.9,
"type": "clickSelf",
"next": [
"StartButton1"
]
},
"StartButton1": {
"filename": "StartButton1.png",
"threshold": 0.94,
"type": "clickSelf",
"next": [
"StartButton2",
"UseMedicine",
"UseStone"
]
},
"StartButton2": {
"id": 2,
"filename": "StartButton2.png",
"threshold": 0.99,
"type": "clickSelf",
"rearDelay": 10000,
"next": [
"PRTS"
]
},
"PRTS": {
"filename": "PRTS.png",
"threshold": 0.98,
"type": "doNothing",
"next": [
"PRTS",
"PrtsErrorConfirm",
"Random"
]
},
"Random": {
"filename": "",
"threshold": 0,
"type": "clickRect",
"specificArea": [
1100,
700,
150,
30
],
"next": [
"Loading",
"StartButton1",
"Random"
]
},
"Loading": {
"filename": "Loading.png",
"threshold": 0.99,
"type": "doNothing",
"next": [
"StartButton1"
]
},
"UseMedicine": {
"filename": "UseMedicine.png",
"threshold": 0.99,
"type": "doNothing",
"next": [
"MedicineConfirm"
]
},
"MedicineConfirm": {
"filename": "MedicineConfirm.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"StartButton1"
]
},
"UseStone": {
"filename": "UseStone.png",
"threshold": 0.99,
"type": "doNothing",
"next": [
"StoneConfirm"
]
},
"StoneConfirm": {
"filename": "MedicineConfirm.png",
"threshold": 0.98,
"type": "clickSelf",
"maxTimes": 0,
"next": [
"StartButton1"
]
},
"PrtsErrorConfirm": {
"filename": "PrtsErrorConfirm.png",
"threshold": 0.98,
"type": "doNothing",
"next": [
"AbandonAction"
]
},
"AbandonAction": {
"filename": "AbandonAction.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"Random"
]
},
"VisitBegin": {
"filename": "",
"threshold": 0,
"type": "doNothing",
"next": [
"Friends",
"FriendsList",
"StartToVisit",
"VisitNext",
"VisitNextBlack",
"ReturnToFriends"
]
},
"ReturnToFriends": {
"filename": "Return.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"Friends",
"ReturnToFriends"
]
},
"Friends": {
"filename": "Friends.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"FriendsList"
]
},
"FriendsList": {
"filename": "FriendsList.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"StartToVisit"
]
},
"StartToVisit": {
"filename": "StartToVisit.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"VisitNext"
]
},
"VisitNext": {
"filename": "VisitNext.png",
"threshold": 0.99,
"type": "clickSelf",
"maxTimes": 20,
"next": [
"VisitNext",
"VisitNextBlack"
]
},
"VisitLimited": {
"filename": "VisitLimited.png",
"threshold": 0.65,
"type": "stop",
"next": []
},
"VisitNextBlack": {
"filename": "VisitNextBlack.png",
"threshold": 0.98,
"type": "stop",
"next": []
}
}
}