Compare commits

...

101 Commits

Author SHA1 Message Date
MistEO
41f56a6e6b update readme 2021-07-24 17:51:47 +08:00
MistEO
8e0430f773 update adb control 2021-07-24 17:41:46 +08:00
MistEO
94c81eb60f update screenshot 2021-07-24 16:52:08 +08:00
MistEO
3eb0328630 rename some function and variable 2021-07-24 16:23:36 +08:00
MistEO
78187cb9c7 update readme 2021-07-24 01:28:26 +08:00
MistEO
d1826e8664 support to print window, and fixed crash when window closed or miniized 2021-07-24 01:25:12 +08:00
MistEO
40b4751616 restructure configer, improve thread safety 2021-07-23 23:48:00 +08:00
MistEO
a01e50571b Update README.md 2021-07-23 16:32:24 +08:00
MistEO
4b244b3aef fixed readme 2021-07-23 00:03:26 +08:00
MistEO
e05430ec0e update version id 2021-07-22 23:48:32 +08:00
MistEO
0a081d4fa2 update readme 2021-07-22 23:45:20 +08:00
MistEO
a6488f0ea6 rename config json key 2021-07-22 22:56:06 +08:00
MistEO
8844d35c2e support control random delay 2021-07-22 22:54:58 +08:00
MistEO
0534e35871 update threshold 2021-07-22 21:47:20 +08:00
MistEO
107d3af5c5 header file unlooping 2021-07-22 21:46:32 +08:00
MistEO
1e170e6c1a fixed some warning, update logger 2021-07-22 19:40:25 +08:00
MistEO
f3773d22c6 update log and config 2021-07-22 10:07:40 +08:00
MistEO
7928a21051 update updater gui 2021-07-22 02:16:53 +08:00
MistEO
2a89b01c1b fixed gui 2021-07-22 02:00:51 +08:00
MistEO
d735404766 add log 2021-07-22 01:07:12 +08:00
MistEO
a8173eb82c fixed count error when use stone or medicine 2021-07-22 00:39:13 +08:00
MistEO
67f52b321c update log 2021-07-21 23:43:47 +08:00
MistEO
6c3540b692 move readme.png to resource 2021-07-21 20:40:54 +08:00
MistEO
dd556817ea update version id 2021-07-21 20:36:29 +08:00
MistEO
c393da2046 Merge pull request #3 from MistEO/feature/new_algorithm
Feature/new algorithm
2021-07-21 20:17:11 +08:00
MistEO
5657af6d94 update config and something 2021-07-21 20:16:33 +08:00
MistEO
f35ef18bd2 add log 2021-07-21 20:16:02 +08:00
MistEO
0fef8e2174 merge "Updater interface modified" 2021-07-21 02:05:23 +08:00
MistEO
ee3afb440e modified the interface of Updater, because VS2019 's O2 optimzation is not friendly to std::optional 2021-07-21 01:43:58 +08:00
MistEO
952861c1e5 update icon and window title 2021-07-20 23:51:47 +08:00
MistEO
dab705a3de fixed bug: process cannot exit 2021-07-20 23:37:27 +08:00
MistEO
17f8353a97 fixed bug: process cannot exit 2021-07-20 23:36:57 +08:00
MistEO
53a1297842 update task sleep logic 2021-07-20 23:29:01 +08:00
MistEO
e589a7498c update identify algorithm 2021-07-20 23:17:10 +08:00
MistEO
ca412965ca add icon for GUI 2021-07-20 21:50:26 +08:00
MistEO
adfed6d276 update release body 2021-07-20 00:50:34 +08:00
MistEO
6fddf69e67 add function of check version update 2021-07-20 00:12:00 +08:00
MistEO
fb3cbb0b7a add set max times function 2021-07-19 21:22:35 +08:00
MistEO
a348139df5 update configer 2021-07-18 23:22:47 +08:00
MistEO
08db7f008d Merge branch 'master' of https://github.com/MistEO/MeoAssistance 2021-07-18 17:43:25 +08:00
MistEO
d66f178aec update gui, add use stone label 2021-07-18 17:43:16 +08:00
MistEO
d51882fd1c Update README.md 2021-07-18 17:29:09 +08:00
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
73 changed files with 3829 additions and 533 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,28 @@
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\Assistance.h" />
<ClInclude Include="include\AsstAux.h" />
<ClInclude Include="include\AsstCaller.h" />
<ClInclude Include="include\AsstDef.h" />
<ClInclude Include="include\Configer.h" />
<ClInclude Include="include\Identify.h" />
<ClInclude Include="include\Logger.hpp" />
<ClInclude Include="include\Updater.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\Updater.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 +62,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 +100,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 +144,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>
<AdditionalDependencies>opencv_world452d.lib;libmeojson.lib;WinInet.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 +173,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;WinInet.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="" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@@ -0,0 +1,71 @@
<?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>
<ClInclude Include="include\Updater.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="include\Logger.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="include\AsstAux.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>
<ClCompile Include="src\Updater.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,51 @@
#pragma once
#include <thread>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <optional>
#include <unordered_map>
#include "AsstDef.h"
#include "Configer.h"
namespace asst {
class WinMacro;
class Identify;
class __declspec(dllexport) Assistance
{
public:
Assistance();
~Assistance();
std::optional<std::string> set_emulator(const std::string & emulator_name = std::string());
void start(const std::string & task);
void stop(bool block = true);
bool set_param(const std::string& type, const std::string& param, const std::string& value);
std::optional<std::string> get_param(const std::string& type, const std::string& param);
bool print_window(const std::string& filename, bool block = true);
private:
static void working_proc(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;
Configer m_configer;
};
}

View File

@@ -0,0 +1,48 @@
#pragma once
#include <string>
#include <Windows.h>
namespace asst {
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;
}
static std::string StringReplaceAll(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;
}
static std::string GetFormatTimeString()
{
SYSTEMTIME curtime;
GetLocalTime(&curtime);
char buff[64] = { 0 };
sprintf_s(buff, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
curtime.wYear, curtime.wMonth, curtime.wDay,
curtime.wHour, curtime.wMinute, curtime.wSecond, curtime.wMilliseconds);
return buff;
}
}

View File

@@ -0,0 +1,20 @@
#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 AsstCatchEmulator(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);
extern __declspec(dllexport) bool CheckVersionUpdate(char * tag_buffer, int tag_bufsize, char * html_url_buffer, int html_bufsize, char * body_buffer, int body_bufsize);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,149 @@
#pragma once
#include <string>
#include <unordered_map>
#include <vector>
#include <ostream>
namespace asst {
const static std::string Version = "release.beta.02";
enum class HandleType
{
Window = 1,
View = 2,
Control = 4
};
static std::ostream& operator<<(std::ostream& os, const HandleType& type)
{
static std::unordered_map<HandleType, std::string> _type_name = {
{HandleType::Window, "Window"},
{HandleType::View, "View"},
{HandleType::Control, "Control"}
};
return os << _type_name.at(type);
}
enum class TaskType {
Invalid = 0,
BasicClick = 1,
DoNothing = 2,
Stop = 4,
PrintWindow,
ClickSelf = 8 | BasicClick,
ClickRect = 16 | BasicClick,
ClickRand = 32 | BasicClick
};
static bool operator&(const TaskType& lhs, const TaskType& rhs)
{
return static_cast<std::underlying_type<TaskType>::type>(lhs) & static_cast<std::underlying_type<TaskType>::type>(rhs);
}
static std::ostream& operator<<(std::ostream& os, const TaskType& task)
{
static std::unordered_map<TaskType, std::string> _type_name = {
{TaskType::Invalid, "Invalid"},
{TaskType::BasicClick, "BasicClick"},
{TaskType::ClickSelf, "ClickSelf"},
{TaskType::ClickRect, "ClickRect"},
{TaskType::ClickRand, "ClickRand"},
{TaskType::DoNothing, "DoNothing"},
{TaskType::Stop, "Stop"},
{TaskType::PrintWindow, "PrintWindow"}
};
return os << _type_name.at(task);
}
enum class AlgorithmType {
JustReturn,
MatchTemplate,
CompareHist
};
static std::ostream& operator<<(std::ostream& os, const AlgorithmType& type)
{
static std::unordered_map<AlgorithmType, std::string> _type_name = {
{AlgorithmType::JustReturn, "JustReturn"},
{AlgorithmType::MatchTemplate, "MatchTemplate"},
{AlgorithmType::CompareHist, "CompareHist"}
};
return os << _type_name.at(type);
}
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) const
{
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;
};
struct HandleInfo {
std::string class_name;
std::string window_name;
};
struct AdbCmd {
std::string path;
std::string connect;
std::string click;
};
struct EmulatorInfo {
std::string name;
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;
};
struct TaskInfo {
std::string filename;
double threshold = 0;
double cache_threshold = 0;
TaskType type = TaskType::Invalid;
std::vector<std::string> next;
int exec_times = 0;
int max_times = INT_MAX;
std::vector<std::string> exceeded_next;
std::vector<std::string> reduce_other_times;
asst::Rect specific_area;
int pre_delay = 0;
int rear_delay = 0;
};
struct Options {
int identify_delay = 0;
bool identify_cache = false;
int control_delay_lower = 0;
int control_delay_upper = 0;
bool print_window = false;
int print_window_delay = 0;
};
}

View File

@@ -0,0 +1,43 @@
#pragma once
#include <string>
#include <unordered_map>
#include <optional>
#include "AsstDef.h"
namespace asst {
class Configer
{
public:
Configer() = default;
~Configer() = default;
Configer(const Configer& rhs);
Configer(Configer&& rhs) noexcept;
bool reload(const std::string& filename);
bool set_param(const std::string& type, const std::string& param, const std::string& value);
std::optional<std::string> get_param(const std::string& type, const std::string& param);
void clear_exec_times();
Configer& operator=(const Configer& rhs);
Configer& operator=(Configer&& rhs) noexcept;
constexpr static int DefaultWindowWidth = 1280;
constexpr static int DefaultWindowHeight = 720;
constexpr static double DefaultThreshold = 0.9;
constexpr static double DefaultCacheThreshold = 0.9;
std::string m_version;
Options m_options;
std::unordered_map<std::string, TaskInfo> m_tasks;
std::unordered_map<std::string, EmulatorInfo> m_handles;
private:
};
}

View File

@@ -0,0 +1,43 @@
#pragma once
#include <unordered_map>
#include <utility>
#include <tuple>
#include <opencv2/opencv.hpp>
#include "AsstDef.h"
namespace asst {
class WinMacro;
class Identify
{
public:
Identify() = default;
~Identify() = default;
void set_use_cache(bool b) noexcept;
bool add_image(const std::string& name, const std::string& path);
// return tuple< algorithmType, suitability, scaled asst::rect>
std::tuple<AlgorithmType, double, asst::Rect> find_image(const cv::Mat& image, const std::string& templ, double threshold = 0.99);
void clear_cache();
private:
cv::Mat image2hist(const cv::Mat& src);
double image_hist_comp(const cv::Mat& src, const cv::MatND& hist);
static 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> find_image(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,102 @@
#pragma once
#include <fstream>
#include <mutex>
#include <chrono>
#include <iostream>
#include "AsstAux.h"
namespace asst {
class Logger {
public:
~Logger() = default;
Logger(const Logger&) = delete;
Logger(Logger&&) = delete;
static Logger& get_instance()
{
static Logger _unique_instance;
return _unique_instance;
}
template <typename... Args>
inline void log_trace(Args &&... args)
{
log("TRC", std::forward<Args>(args)...);
}
template <typename... Args>
inline void log_info(Args &&... args)
{
log("INF", std::forward<Args>(args)...);
}
template <typename... Args>
inline void log_error(Args &&... args)
{
log("ERR", std::forward<Args>(args)...);
}
private:
Logger() = default;
template <typename... Args>
void log(const std::string& level, Args &&... args)
{
std::unique_lock<std::mutex> trace_lock(m_trace_mutex);
char buff[128] = { 0 };
sprintf_s(buff, "[%s][%s][Px%x][Tx%x]",
asst::GetFormatTimeString().c_str(),
level.c_str(), _getpid(), ::GetCurrentThreadId());
if (level == "ERR" || level == "INF"
#ifdef _DEBUG
|| level == "TRC"
#endif
) {
stream_args(std::cout, buff, std::forward<Args>(args)...);
}
std::ofstream out_stream(asst::GetCurrentDir() + "asst.log", std::ios::out | std::ios::app);
stream_args(out_stream, buff, std::forward<Args>(args)...);
}
template <typename T, typename... Args>
inline void stream_args(std::ostream& os, T&& first, Args && ...rest)
{
os << first << " ";
stream_args(os, std::forward<Args>(rest)...);
}
inline void stream_args(std::ostream& os)
{
os << std::endl;
}
std::mutex m_trace_mutex;
};
class LoggerAux {
public:
LoggerAux(const std::string& func_name)
: m_func_name(func_name),
m_start_time(std::chrono::system_clock::now())
{
Logger::get_instance().log_trace(m_func_name, " | enter");
}
~LoggerAux()
{
auto duration = std::chrono::system_clock::now() - m_start_time;
Logger::get_instance().log_trace(m_func_name, " | leave,",
std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(), "ms");
}
private:
std::string m_func_name;
std::chrono::time_point<std::chrono::system_clock> m_start_time;
};
}
#define DebugTrace Logger::get_instance().log_trace
#define DebugTraceInfo Logger::get_instance().log_info
#define DebugTraceError Logger::get_instance().log_error
#define DebugTraceFunction LoggerAux _func_aux(__FUNCTION__)

View File

@@ -0,0 +1,39 @@
#pragma once
#include <string>
#include <optional>
#include <mutex>
namespace asst {
struct __declspec(dllexport) VersionInfo {
std::string tag_name;
std::string html_url;
std::string down_url;
std::string author_name;
std::string created_time;
std::string body;
};
class __declspec(dllexport) Updater
{
static const std::string GithubReleaseLastestApiUrl;
static const std::string GithubReleaseApiUrl;
public:
~Updater() = default;
Updater(const Updater&) = delete;
Updater(Updater&&) = delete;
static Updater& get_instance();
bool has_new_version();
const VersionInfo & get_version_info() const noexcept;
private:
Updater() = default;
std::optional<std::string> request_github_api();
bool m_has_new_version = false;
VersionInfo m_lastest_version;
std::mutex m_mutex;
};
}

View File

@@ -0,0 +1,45 @@
#pragma once
#include <string>
#include <random>
#include <Windows.h>
#include <opencv2/opencv.hpp>
#include "AsstDef.h"
namespace asst {
class WinMacro
{
public:
WinMacro(const EmulatorInfo & info, 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 click(const Rect & rect);
cv::Mat getImage(const Rect& rect);
Rect getWindowRect();
const EmulatorInfo& getEmulatorInfo() const noexcept { return m_emulator_info; }
const HandleType& getHandleType() const noexcept { return m_handle_type; }
static double getScreenScale();
private:
bool findHandle();
DWORD callCmd(const std::string& cmd, int wait_time = 1000);
const EmulatorInfo m_emulator_info;
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,312 @@
#include "Assistance.h"
#include "WinMacro.h"
#include "Configer.h"
#include "Identify.h"
#include "Logger.hpp"
#include "AsstAux.h"
#include <time.h>
#include <filesystem>
using namespace asst;
Assistance::Assistance()
{
DebugTraceFunction;
m_configer.reload(GetResourceDir() + "config.json");
m_pIder = std::make_shared<Identify>();
for (auto&& [name, info] : m_configer.m_tasks)
{
m_pIder->add_image(name, GetResourceDir() + info.filename);
}
m_pIder->set_use_cache(m_configer.m_options.identify_cache);
m_working_thread = std::thread(working_proc, this);
}
Assistance::~Assistance()
{
DebugTraceFunction;
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::set_emulator(const std::string& emulator_name)
{
DebugTraceFunction;
stop();
auto create_handles = [&](const EmulatorInfo& info) -> bool {
m_pWindow = std::make_shared<WinMacro>(info, HandleType::Window);
m_pView = std::make_shared<WinMacro>(info, HandleType::View);
m_pCtrl = std::make_shared<WinMacro>(info, HandleType::Control);
return m_pWindow->captured() && m_pView->captured() && m_pCtrl->captured();
};
bool ret = false;
std::string cor_name = emulator_name;
std::unique_lock<std::mutex> lock(m_mutex);
if (emulator_name.empty()) {
for (auto&& [name, info] : m_configer.m_handles)
{
ret = create_handles(info);
if (ret) {
cor_name = name;
break;
}
}
}
else {
ret = create_handles(m_configer.m_handles[emulator_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)
{
DebugTraceFunction;
DebugTrace("Start |", task);
if (m_thread_running || !m_inited) {
return;
}
std::unique_lock<std::mutex> lock(m_mutex);
m_configer.clear_exec_times();
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)
{
DebugTraceFunction;
DebugTrace("Stop |", block ? "block" : "non block");
std::unique_lock<std::mutex> lock;
if (block) { // 外部调用
lock = std::unique_lock<std::mutex>(m_mutex);
m_configer.clear_exec_times();
}
m_thread_running = false;
m_next_tasks.clear();
m_pIder->clear_cache();
}
bool Assistance::set_param(const std::string& type, const std::string& param, const std::string& value)
{
DebugTraceFunction;
DebugTrace("SetParam |", type, param, value);
std::unique_lock<std::mutex> lock(m_mutex);
return m_configer.set_param(type, param, value);
}
std::optional<std::string> Assistance::get_param(const std::string& type, const std::string& param)
{
// DebugTraceFunction;
std::unique_lock<std::mutex> lock(m_mutex);
return m_configer.get_param(type, param);
}
bool asst::Assistance::print_window(const std::string& filename, bool block)
{
DebugTraceFunction;
DebugTrace("print_window |", block ? "block" : "non block");
std::unique_lock<std::mutex> lock;
if (block) { // 外部调用
lock = std::unique_lock<std::mutex>(m_mutex);
}
auto cur_image = m_pView->getImage(m_pView->getWindowRect());
if (cur_image.empty() || cur_image.cols < m_configer.DefaultWindowWidth || cur_image.rows < m_configer.DefaultWindowHeight) {
DebugTraceError("Window image error");
return false;
}
// 把模拟器边框的一圈裁剪掉,不然企鹅物流识别不出来
auto&& window_info = m_pView->getEmulatorInfo();
int x_offset = -window_info.x_offset + 5;
int y_offset = -window_info.y_offset;// + 5;
int width = m_configer.DefaultWindowWidth - 5;
int height = m_configer.DefaultWindowHeight - 5;
cv::Mat resize_mat( cur_image, cv::Rect(x_offset, y_offset, width, height));
bool ret = cv::imwrite(filename.c_str(), resize_mat);
if (ret) {
DebugTraceInfo("PrintWindow to", filename);
}
else {
DebugTraceError("PrintWindow error", filename);
}
return ret;
}
void Assistance::working_proc(Assistance* pThis)
{
DebugTraceFunction;
while (!pThis->m_thread_exit) {
std::unique_lock<std::mutex> lock(pThis->m_mutex);
if (pThis->m_thread_running) {
auto cur_image = pThis->m_pView->getImage(pThis->m_pView->getWindowRect());
if (cur_image.empty()) {
DebugTraceError("Unable to capture window image!!!");
pThis->stop(false);
continue;
}
if (cur_image.cols < pThis->m_configer.DefaultWindowWidth || cur_image.rows < pThis->m_configer.DefaultWindowHeight) {
DebugTraceInfo("Window Could not be minimized!!!");
pThis->m_pWindow->showWindow();
pThis->m_condvar.wait_for(lock,
std::chrono::milliseconds(pThis->m_configer.m_options.identify_delay),
[&]() -> bool { return !pThis->m_thread_running; });
continue;
}
std::string matched_task;
Rect matched_rect;
for (auto&& task_name : pThis->m_next_tasks) {
double threshold = pThis->m_configer.m_tasks[task_name].threshold;
double cache_threshold = pThis->m_configer.m_tasks[task_name].cache_threshold;
auto&& [algorithm, value, rect] = pThis->m_pIder->find_image(cur_image, task_name, threshold);
DebugTrace(task_name, "Type:", algorithm, "Value:", value);
if (algorithm == AlgorithmType::JustReturn ||
(algorithm == AlgorithmType::MatchTemplate && value >= threshold)
|| (algorithm == AlgorithmType::CompareHist && value >= cache_threshold)) {
matched_task = task_name;
matched_rect = rect;
break;
}
}
if (!matched_task.empty()) {
auto&& task = pThis->m_configer.m_tasks[matched_task];
DebugTraceInfo("***Matched***", matched_task, "Type:", task.type);
if (task.pre_delay > 0) {
DebugTrace("PreDelay", task.pre_delay);
// std::this_thread::sleep_for(std::chrono::milliseconds(task.pre_delay));
bool cv_ret = pThis->m_condvar.wait_for(lock, std::chrono::milliseconds(task.pre_delay),
[&]() -> bool { return !pThis->m_thread_running; });
if (cv_ret) { continue; }
}
if (task.max_times != INT_MAX) {
DebugTrace("CurTimes:", task.exec_times, "MaxTimes:", task.max_times);
}
if (task.exec_times < task.max_times) {
if ((task.type & TaskType::BasicClick)
&& pThis->m_configer.m_options.control_delay_upper != 0) {
static std::default_random_engine rand_engine(std::chrono::system_clock::now().time_since_epoch().count());
static std::uniform_int_distribution<unsigned> rand_uni(pThis->m_configer.m_options.control_delay_lower, pThis->m_configer.m_options.control_delay_upper);
int delay = rand_uni(rand_engine);
DebugTraceInfo("Random Delay", delay, "ms");
bool cv_ret = pThis->m_condvar.wait_for(lock, std::chrono::milliseconds(delay),
[&]() -> bool { return !pThis->m_thread_running; });
if (cv_ret) { continue; }
}
switch (task.type) {
case TaskType::ClickRect:
matched_rect = task.specific_area;
[[fallthrough]];
case TaskType::ClickSelf:
pThis->m_pCtrl->click(matched_rect);
break;
case TaskType::ClickRand:
pThis->m_pCtrl->click(pThis->m_pCtrl->getWindowRect());
break;
case TaskType::DoNothing:
break;
case TaskType::Stop:
DebugTrace("TaskType is Stop");
pThis->stop(false);
continue;
break;
case TaskType::PrintWindow:
if (pThis->m_configer.m_options.print_window) {
int print_delay = pThis->m_configer.m_options.print_window_delay;
DebugTraceInfo("Ready to print window, delay", print_delay);
pThis->m_condvar.wait_for(lock,
std::chrono::milliseconds(print_delay),
[&]() -> bool { return !pThis->m_thread_running; });
std::string dirname = GetCurrentDir() + "screenshot\\";
std::filesystem::create_directory(dirname);
auto time_str = StringReplaceAll(StringReplaceAll(GetFormatTimeString(), " ", "_"), ":", "-");
std::string filename = dirname + time_str + ".png";
pThis->print_window(filename, false);
}
break;
default:
DebugTraceError("Unknown option type:", task.type);
break;
}
++task.exec_times;
for (auto&& reduce : task.reduce_other_times) {
--pThis->m_configer.m_tasks[reduce].exec_times;
DebugTrace("Reduce exec times", reduce, pThis->m_configer.m_tasks[reduce].exec_times);
}
if (task.rear_delay > 0) {
DebugTrace("RearDelay", task.rear_delay);
// std::this_thread::sleep_for(std::chrono::milliseconds(task.rear_delay));
auto cv_ret = pThis->m_condvar.wait_for(lock, std::chrono::milliseconds(task.rear_delay),
[&]() -> bool { return !pThis->m_thread_running; });
if (cv_ret) { continue; }
}
pThis->m_next_tasks = pThis->m_configer.m_tasks[matched_task].next;
}
else {
DebugTraceInfo("Reached limit");
pThis->m_next_tasks = pThis->m_configer.m_tasks[matched_task].exceeded_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(pThis->m_configer.m_options.identify_delay),
[&]() -> bool { return !pThis->m_thread_running; });
}
else {
pThis->m_condvar.wait(lock);
}
}
}

View File

@@ -0,0 +1,86 @@
#include "AsstCaller.h"
#include "Updater.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 AsstCatchEmulator(asst::Assistance* p_asst)
{
if (p_asst == NULL) {
return false;
}
auto ret = p_asst->set_emulator();
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->set_param(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->get_param(type, param);
if (!ret) {
return false;
}
strcpy_s(buffer, buffer_size, ret.value().c_str());
return true;
}
bool CheckVersionUpdate(char* tag_buffer, int tag_bufsize, char* html_url_buffer, int html_bufsize, char* body_buffer, int body_bufsize)
{
bool ret = asst::Updater::get_instance().has_new_version();
if (!ret) {
return false;
}
auto && info = asst::Updater::get_instance().get_version_info();
strcpy_s(tag_buffer, tag_bufsize, info.tag_name.c_str());
strcpy_s(html_url_buffer, html_bufsize, info.html_url.c_str());
strcpy_s(body_buffer, body_bufsize, info.body.c_str());
return true;
}

View File

@@ -0,0 +1,261 @@
#include "Configer.h"
#include <fstream>
#include <sstream>
#include <algorithm>
#include "json.h"
#include "Logger.hpp"
using namespace asst;
Configer::Configer(const Configer& rhs)
: m_version(rhs.m_version),
m_options(rhs.m_options),
m_tasks(rhs.m_tasks),
m_handles(rhs.m_handles)
{
}
Configer::Configer(Configer&& rhs) noexcept
: m_version(std::move(rhs.m_version)),
m_options(std::move(rhs.m_options)),
m_tasks(std::move(rhs.m_tasks)),
m_handles(std::move(rhs.m_handles))
{
}
bool Configer::reload(const std::string& filename)
{
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();
Configer temp;
try {
temp.m_version = root["version"].as_string();
auto options_obj = root["options"].as_object();
temp.m_options.identify_delay = options_obj["identifyDelay"].as_integer();
temp.m_options.identify_cache = options_obj["identifyCache"].as_boolean();
temp.m_options.control_delay_lower = options_obj["controlDelayRange"][0].as_integer();
temp.m_options.control_delay_upper = options_obj["controlDelayRange"][1].as_integer();
temp.m_options.print_window = options_obj["printWindow"].as_boolean();
temp.m_options.print_window_delay = options_obj["printWindowDelay"].as_integer();
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();
if (task_json.exist("threshold")) {
task_info.threshold = task_json["threshold"].as_double();
}
else {
task_info.threshold = DefaultThreshold;
}
if (task_json.exist("cacheThreshold")) {
task_info.cache_threshold = task_json["cacheThreshold"].as_double();
}
else {
task_info.cache_threshold = DefaultCacheThreshold;
}
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 if (type == "printwindow") {
task_info.type = TaskType::PrintWindow;
}
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("exceededNext")) {
auto next_arr = task_json["exceededNext"].as_array();
for (auto&& name : next_arr) {
task_info.exceeded_next.emplace_back(name.as_string());
}
}
else {
task_info.exceeded_next.emplace_back("Stop");
}
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();
}
if (task_json.exist("reduceOtherTimes")) {
auto reduce_arr = task_json["reduceOtherTimes"].as_array();
for (auto&& reduce : reduce_arr) {
task_info.reduce_other_times.emplace_back(reduce.as_string());
}
}
auto next_arr = task_json["next"].as_array();
for (auto&& name : next_arr) {
task_info.next.emplace_back(name.as_string());
}
temp.m_tasks.emplace(name, task_info);
}
auto handle_obj = root["handle"].as_object();
for (auto&& [name, emulator_json] : handle_obj) {
EmulatorInfo emulator_info;
emulator_info.name = name;
auto window_arr = emulator_json["window"].as_array();
for (auto&& info : window_arr) {
HandleInfo handle_info;
handle_info.class_name = info["class"].as_string();
handle_info.window_name = info["window"].as_string();
emulator_info.window.emplace_back(handle_info);
}
auto view_arr = emulator_json["view"].as_array();
for (auto&& info : view_arr) {
HandleInfo handle_info;
handle_info.class_name = info["class"].as_string();
handle_info.window_name = info["window"].as_string();
emulator_info.view.emplace_back(handle_info);
}
auto ctrl_arr = emulator_json["control"].as_array();
for (auto&& info : ctrl_arr) {
HandleInfo handle_info;
handle_info.class_name = info["class"].as_string();
handle_info.window_name = info["window"].as_string();
emulator_info.control.emplace_back(handle_info);
}
if (emulator_json.exist("adbControl")) {
emulator_info.is_adb = true;
// meojson的bug暂时没空修先转个字符串
emulator_info.adb.path = StringReplaceAll(emulator_json["adbControl"]["path"].as_string(), "\\\\", "\\");
emulator_info.adb.connect = emulator_json["adbControl"]["connect"].as_string();
emulator_info.adb.click = emulator_json["adbControl"]["click"].as_string();
}
emulator_info.width = emulator_json["width"].as_integer();
emulator_info.height = emulator_json["height"].as_integer();
emulator_info.x_offset = emulator_json["xOffset"].as_integer();
emulator_info.y_offset = emulator_json["yOffset"].as_integer();
temp.m_handles.emplace(name, emulator_info);
}
}
catch (json::exception& e) {
DebugTraceError("Load config json error!", e.what());
return false;
}
*this = std::move(temp);
return true;
}
bool Configer::set_param(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::get_param(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::clear_exec_times()
{
for (auto&& t : m_tasks) {
t.second.exec_times = 0;
}
}
Configer& asst::Configer::operator=(const Configer& rhs)
{
m_version = rhs.m_version;
m_options = rhs.m_options;
m_tasks = rhs.m_tasks;
m_handles = rhs.m_handles;
return *this;
}
Configer& asst::Configer::operator=(Configer&& rhs) noexcept
{
m_version = std::move(rhs.m_version);
m_options = std::move(rhs.m_options);
m_tasks = std::move(rhs.m_tasks);
m_handles = std::move(rhs.m_handles);
return *this;
}

View File

@@ -0,0 +1,109 @@
#include "Identify.h"
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>
using namespace asst;
using namespace cv;
bool Identify::add_image(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::set_use_cache(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::image_hist_comp(const cv::Mat& src, const cv::MatND& hist)
{
// keep the interface return value unchanged
return 1 - compareHist(image2hist(src), hist, CV_COMP_BHATTACHARYYA);
}
std::pair<double, cv::Point> Identify::find_image(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_CCOEFF_NORMED);
double minVal = 0, maxVal = 0;
cv::Point minLoc, maxLoc;
minMaxLoc(matched, &minVal, &maxVal, &minLoc, &maxLoc);
return { maxVal, maxLoc };
}
std::tuple<AlgorithmType, double, asst::Rect> Identify::find_image(const Mat& cur, const std::string& templ, double threshold)
{
if (m_mat_map.find(templ) == m_mat_map.cend()) {
return { AlgorithmType::JustReturn, 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 = image_hist_comp(cur(rect), hist);
return { AlgorithmType::CompareHist, value, cvrect2rect(rect).center_zoom(0.8) };
}
else {
auto&& templ_mat = m_mat_map.at(templ);
auto&& [value, point] = find_image(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 { AlgorithmType::MatchTemplate, 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,98 @@
#include "Updater.h"
#include <stdio.h>
#include <Windows.h>
#include <WinInet.h>
#include "json.h"
#include "AsstDef.h"
#include "Logger.hpp"
using namespace asst;
const std::string Updater::GithubReleaseLastestApiUrl = "https://api.github.com/repos/MistEO/MeoAssistance/releases/latest";
const std::string Updater::GithubReleaseApiUrl = "https://api.github.com/repos/MistEO/MeoAssistance/releases/latest";
Updater& Updater::get_instance()
{
static Updater unique_instance;
return unique_instance;
}
bool Updater::has_new_version()
{
auto req_ret = request_github_api();
if (!req_ret) {
DebugTraceInfo("Requeset Error");
return false;
}
auto parse_ret = json::parser::parse(req_ret.value());
if (!parse_ret) {
DebugTraceInfo("Parse Error");
return false;
}
json::value root = std::move(parse_ret).value();
std::unique_lock<std::mutex> lock(m_mutex);
try {
m_lastest_version.tag_name = root["tag_name"].as_string();
m_lastest_version.html_url = root["html_url"].as_string();
m_lastest_version.author_name = root["author"]["login"].as_string();
m_lastest_version.created_time = root["created_at"].as_string();
m_lastest_version.body = root["body"].as_string();
auto assets = root["assets"].as_array();
if (assets.size() == 1) {
m_lastest_version.down_url = assets[0]["browser_download_url"].as_string();
}
}
catch (json::exception& exp) {
DebugTraceError("Json Error", exp.what());
return false;
}
if (m_lastest_version.tag_name > Version) {
m_has_new_version = true;
return true;
}
else {
return false;
}
}
const VersionInfo & Updater::get_version_info() const noexcept
{
return m_lastest_version;
}
std::optional<std::string> Updater::request_github_api()
{
HINTERNET h_session = ::InternetOpenA("GithubRelease", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (h_session == NULL) {
return std::nullopt;
}
HINTERNET h_http = ::InternetOpenUrlA(h_session, GithubReleaseLastestApiUrl.c_str(), NULL, 0, INTERNET_FLAG_DONT_CACHE, 0);
if (h_http == NULL) {
return std::nullopt;
}
std::string response;
DWORD buff_size = 4096;
char *buffer = new char[buff_size];
DWORD number = 1;
while (number > 0) {
memset(buffer, 0, buff_size);
InternetReadFile(h_http, buffer, buff_size, &number);
if (number != 0) {
response += std::string(buffer, number);
}
}
delete[] buffer;
buffer = NULL;
InternetCloseHandle(h_http);
h_http = NULL;
InternetCloseHandle(h_session);
h_session = NULL;
return response;
}

View File

@@ -0,0 +1,319 @@
#include "WinMacro.h"
#include <vector>
#include <utility>
#include <algorithm>
#include <chrono>
#include <stdint.h>
#include <WinUser.h>
#include "AsstDef.h"
#include "Logger.hpp"
using namespace asst;
WinMacro::WinMacro(const EmulatorInfo& info, HandleType type)
: m_emulator_info(info),
m_handle_type(type),
m_rand_engine(std::chrono::system_clock::now().time_since_epoch().count())
{
findHandle();
}
bool WinMacro::captured() const noexcept
{
return m_handle != NULL && ::IsWindow(m_handle);
}
bool WinMacro::findHandle()
{
std::vector<HandleInfo> handle_vec;
switch (m_handle_type) {
case HandleType::Window:
m_width = m_emulator_info.width;
m_height = m_emulator_info.height;
handle_vec = m_emulator_info.window;
break;
case HandleType::View:
handle_vec = m_emulator_info.view;
break;
case HandleType::Control:
m_is_adb = m_emulator_info.is_adb;
m_x_offset = m_emulator_info.x_offset;
m_y_offset = m_emulator_info.y_offset;
handle_vec = m_emulator_info.control;
break;
default:
DebugTraceError("Handle type error!", m_handle_type);
return false;
}
m_handle = NULL;
for (auto&& handle_info : handle_vec)
{
wchar_t* class_wbuff = NULL;
if (!handle_info.class_name.empty()) {
size_t class_len = (handle_info.class_name.size() + 1) * 2;
class_wbuff = new wchar_t[class_len];
::MultiByteToWideChar(CP_UTF8, 0, handle_info.class_name.c_str(), -1, class_wbuff, class_len);
}
wchar_t* window_wbuff = NULL;
if (!handle_info.window_name.empty()) {
size_t window_len = (handle_info.window_name.size() + 1) * 2;
window_wbuff = new wchar_t[window_len];
memset(window_wbuff, 0, window_len);
::MultiByteToWideChar(CP_UTF8, 0, handle_info.window_name.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 = '"' + StringReplaceAll(m_emulator_info.adb.path, "[EmulatorPath]", adb_dir) + '"';
std::string connect_cmd = adb_dir + m_emulator_info.adb.connect;
auto ret = callCmd(connect_cmd, 10000);
if (ret != 0) {
DebugTraceError("Connect ADB Error", ret);
return false;
}
m_click_cmd = adb_dir + m_emulator_info.adb.click;
}
DebugTrace("Handle:", m_handle, "Name:", m_emulator_info.name, "Type:", m_handle_type);
if (m_handle != NULL) {
return true;
}
else {
return false;
}
}
DWORD asst::WinMacro::callCmd(const std::string& cmd, int wait_time)
{
// int ret = system(cmd.c_str());
STARTUPINFOA startup_info;
PROCESS_INFORMATION process_info;
ZeroMemory(&startup_info, sizeof(startup_info));
ZeroMemory(&process_info, sizeof(process_info));
DWORD ret = -1;
if (::CreateProcessA(NULL, const_cast<LPSTR>(cmd.c_str()), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &startup_info, &process_info)) {
::WaitForSingleObject(process_info.hProcess, wait_time);
::GetExitCodeProcess(process_info.hProcess, &ret);
::CloseHandle(process_info.hProcess);
::CloseHandle(process_info.hThread);
DebugTrace("Call", cmd, "—— ret", ret);
}
else {
DebugTraceError("Create process error");
}
return ret;
}
bool WinMacro::resizeWindow(int width, int height)
{
if (m_handle_type != HandleType::Window || !::IsWindow(m_handle)) {
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 || !::IsWindow(m_handle)) {
return false;
}
return ::ShowWindow(m_handle, SW_RESTORE);
}
bool WinMacro::hideWindow()
{
if (m_handle_type != HandleType::Window || !::IsWindow(m_handle)) {
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 || !::IsWindow(m_handle)) {
return false;
}
if (m_is_adb) {
int x = (p.x + m_x_offset);
int y = (p.y + m_y_offset);
std::string cur_cmd = StringReplaceAll(m_click_cmd, "[x]", std::to_string(x));
cur_cmd = StringReplaceAll(cur_cmd, "[y]", std::to_string(y));
auto ret = callCmd(cur_cmd);
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, "corr:", 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::click(const Rect& rect)
{
if (m_handle_type != HandleType::Control || !::IsWindow(m_handle)) {
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()
{
if (!::IsWindow(m_handle)) {
return Rect();
}
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 || !::IsWindow(m_handle)) {
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,24 @@
<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="Meo明日方舟辅助" Height="500" Width="400" Loaded="OnLoaded">
<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,270,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_startSanity"/>
<Button x:Name="button_stop" Content="停止" HorizontalAlignment="Left" Margin="50,350,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,270,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"/>
<Label x:Name="stone_times" Content="" HorizontalAlignment="Left" Margin="230,144,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.702,0.403"/>
<CheckBox x:Name="checkBox_maxTimes" Content="指定次数" HorizontalAlignment="Left" Margin="50,200,0,0" VerticalAlignment="Top" Checked="checkBox_maxTimes_Checked" Unchecked="checkBox_maxTimes_Checked"/>
<TextBox x:Name="textBox_maxTimes" HorizontalAlignment="Left" Height="23" Margin="124,198,0,0" TextWrapping="Wrap" Text="0" VerticalAlignment="Top" Width="47" TextChanged="textBox_maxTimes_TextChanged" InputMethod.IsInputMethodEnabled="False"/>
<Label x:Name="label" Content="次" HorizontalAlignment="Left" Margin="176,193,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.397,-0.745"/>
</Grid>
</Window>

View File

@@ -0,0 +1,157 @@
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 private extern IntPtr CreateAsst();
[DllImport("MeoAssistance.dll")] static private extern void DestoryAsst(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static private extern bool AsstCatchEmulator(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static private extern void AsstStart(IntPtr ptr, string task);
[DllImport("MeoAssistance.dll")] static private extern void AsstStop(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static private extern bool AsstSetParam(IntPtr p_asst, string type, string param, string value);
[DllImport("MeoAssistance.dll")]
static private extern bool AsstGetParam(
IntPtr p_asst, string type, string param,
[In, Out] StringBuilder lp_string, int buffer_size);
private IntPtr p_asst;
UpdateDialog updateDialog;
private DispatcherTimer update_times = new DispatcherTimer();
public MainWindow()
{
InitializeComponent();
}
~MainWindow()
{
DestoryAsst(p_asst);
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
updateDialog = new UpdateDialog();
updateDialog.CheckUpdateAndShowDialog();
updateDialog.Close();
p_asst = CreateAsst();
update_times.Tick += new EventHandler(updateExecTimes);
update_times.Interval = TimeSpan.FromSeconds(1);
}
private void button_Click_startSanity(object sender, RoutedEventArgs e)
{
bool catched = AsstCatchEmulator(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 = "";
stone_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)
{
if (checkBox_useStone.IsChecked == true)
{
String text = textBox_useStone.Text != String.Empty ? textBox_useStone.Text : "0";
AsstSetParam(p_asst, "task.maxTimes", "StoneConfirm", text);
}
}
private void checkBox_useStone_Checked(object sender, RoutedEventArgs e)
{
if (checkBox_useStone.IsChecked == true)
{
AsstSetParam(p_asst, "task.type", "UseStone", "doNothing");
String text = textBox_useStone.Text != String.Empty ? textBox_useStone.Text : "0";
AsstSetParam(p_asst, "task.maxTimes", "StoneConfirm", text);
}
else
{
AsstSetParam(p_asst, "task.type", "UseStone", "stop");
AsstSetParam(p_asst, "task.maxTimes", "StoneConfirm", "0");
}
}
private void button_Click_visit(object sender, RoutedEventArgs e)
{
bool catched = AsstCatchEmulator(p_asst);
catch_status.Content = "捕获模拟器窗口:" + catched;
AsstStart(p_asst, "VisitBegin");
}
private void updateExecTimes(object sender, EventArgs e)
{
StringBuilder buff_start = new StringBuilder(16);
AsstGetParam(p_asst, "task.execTimes", "StartButton2", buff_start, 16);
exec_times.Content = "已开始行动 " + buff_start + " 次";
if (checkBox_useStone.IsChecked == true)
{
StringBuilder buff_stone = new StringBuilder(16);
AsstGetParam(p_asst, "task.execTimes", "StoneConfirm", buff_stone, 16);
stone_times.Content = "已碎石 " + buff_stone + " 个";
}
}
private void checkBox_maxTimes_Checked(object sender, RoutedEventArgs e)
{
if (checkBox_maxTimes.IsChecked == true)
{
String text = textBox_maxTimes.Text != String.Empty ? textBox_maxTimes.Text : "0";
AsstSetParam(p_asst, "task.maxTimes", "StartButton1", text);
}
else
{
AsstSetParam(p_asst, "task.maxTimes", "StartButton1", int.MaxValue.ToString());
}
}
private void textBox_maxTimes_TextChanged(object sender, TextChangedEventArgs e)
{
if (checkBox_maxTimes.IsChecked == true)
{
String text = textBox_maxTimes.Text != String.Empty ? textBox_maxTimes.Text : "0";
AsstSetParam(p_asst, "task.maxTimes", "StartButton1", text);
}
}
}
}

View File

@@ -0,0 +1,146 @@
<?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>0.2.0.0</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>
<PropertyGroup>
<ApplicationIcon>favicon.ico</ApplicationIcon>
</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>
<Compile Include="UpdateDialog.xaml.cs">
<DependentUpon>UpdateDialog.xaml</DependentUpon>
</Compile>
<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>
<Page Include="UpdateDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</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>
<ItemGroup>
<Resource Include="favicon.ico" />
</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>

View File

@@ -0,0 +1,16 @@
<Window x:Class="MeoAsstGui.UpdateDialog"
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="有新版本" Height="500" Width="400">
<Grid>
<Label x:Name="label_tag" Content="" HorizontalAlignment="Center" Margin="10,25,10.333,0" VerticalAlignment="Top" Height="50" Width="373" FontSize="24"/>
<Label x:Name="label_body" Content="" HorizontalAlignment="Left" Margin="50,80,0,0" VerticalAlignment="Top" Height="281" Width="290" FontSize="16"/>
<Button x:Name="button_confirm" Content="前往下载" HorizontalAlignment="Left" Margin="50,366,0,0" VerticalAlignment="Top" Width="120" Height="60" Click="button_confirm_Click"/>
<Button x:Name="button_cancer" Content="下次一定" HorizontalAlignment="Left" Margin="220,366,0,0" VerticalAlignment="Top" Width="120" Height="60" Click="button_cancer_Click"/>
</Grid>
</Window>

View File

@@ -0,0 +1,69 @@
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.Shapes;
using System.Runtime.InteropServices;
namespace MeoAsstGui
{
/// <summary>
/// UpdateDialog.xaml 的交互逻辑
/// </summary>
public partial class UpdateDialog : Window
{
[DllImport("MeoAssistance.dll")]
static private extern bool CheckVersionUpdate(
[In, Out] StringBuilder tag, int tag_bufsize,
[In, Out] StringBuilder html_url, int html_bufsize,
[In, Out] StringBuilder body, int body_bufsize);
public UpdateDialog()
{
InitializeComponent();
}
private String m_htmlUrl;
public void CheckUpdateAndShowDialog()
{
StringBuilder tag = new StringBuilder(64);
StringBuilder html_url = new StringBuilder(512);
StringBuilder body = new StringBuilder(4096);
bool ret = CheckVersionUpdate(tag, 64, html_url, 512, body, 4096);
if (!ret)
{
return;
}
label_tag.Content = "新版本:" + tag;
byte[] buffer1 = Encoding.Default.GetBytes(body.ToString());
byte[] buffer2 = Encoding.Convert(Encoding.UTF8, Encoding.Default, buffer1, 0, buffer1.Length);
string strBuffer = Encoding.Default.GetString(buffer2, 0, buffer2.Length);
strBuffer = strBuffer.Replace("\\r\\n", "\r\n");
int len = strBuffer.Length > 128 ? 128 : strBuffer.Length;
label_body.Content = strBuffer.Substring(0, len) + "\n......";
m_htmlUrl = html_url.ToString();
ShowDialog();
}
private void button_cancer_Click(object sender, RoutedEventArgs e)
{
Close();
}
private void button_confirm_Click(object sender, RoutedEventArgs e)
{
System.Diagnostics.Process.Start(m_htmlUrl);
Close();
}
}
}

BIN
MeoAsstGui/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

132
README.md
View File

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

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>

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

@@ -0,0 +1,37 @@
#include "Assistance.h"
#include "Updater.h"
#include "Logger.hpp"
int main(int argc, char** argv)
{
using namespace asst;
bool up = Updater::get_instance().has_new_version();
if (up) {
auto && info = Updater::get_instance().get_version_info();
std::cout << "ÓÐа汾£º" << info.tag_name << std::endl;
std::cout << "µØÖ·£º" << info.html_url << std::endl;
}
Assistance asst;
auto ret = asst.set_emulator();
if (!ret) {
DebugTraceError("Can't Find Emulator or Permission denied.");
getchar();
return -1;
}
else {
DebugTraceInfo("Find Emulator:", ret.value());
}
DebugTraceInfo("Start");
asst.start("SanityBegin");
getchar();
DebugTraceInfo("Stop");
asst.stop();
return 0;
}

Submodule meojson updated: 0a86b19d2a...d6d07f5e6c

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
readme/gui.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
resource/AbandonAction.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

BIN
resource/CollectCredit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
resource/CreditStore.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 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

BIN
resource/Mall.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 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

BIN
resource/PopupCancel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
resource/PopupConfirm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 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: 3.5 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

467
resource/config.json Normal file
View File

@@ -0,0 +1,467 @@
{
"version": "0.4",
"options": {
"identifyCache": true,
"identifyDelay": 1000,
"printWindow": true,
"printWindowDelay": 3000,
"controlDelayRange": [
0,
0
]
},
"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.8,
"type": "clickSelf",
"next": [
"StartButton1"
]
},
"StartButton1": {
"filename": "StartButton1.png",
"threshold": 0.8,
"type": "clickSelf",
"next": [
"StartButton2",
"UseMedicine",
"UseStone"
]
},
"StartButton2": {
"filename": "StartButton2.png",
"type": "clickSelf",
"rearDelay": 20000,
"next": [
"StartButton2",
"PRTS"
]
},
"PRTS": {
"filename": "PRTS.png",
"type": "doNothing",
"rearDelay": 5000,
"next": [
"PRTS",
"PrtsErrorConfirm",
"EndOfAction"
]
},
"EndOfAction": {
"filename": "",
"threshold": 0,
"type": "printWindow",
"next": [
"Random"
]
},
"Random": {
"filename": "",
"threshold": 0,
"type": "clickRect",
"specificArea": [
1100,
700,
150,
30
],
"next": [
"Loading",
"StartButton1",
"Random"
]
},
"Loading": {
"filename": "Loading.png",
"type": "doNothing",
"next": [
"StartButton1"
]
},
"UseMedicine": {
"filename": "UseMedicine.png",
"type": "doNothing",
"next": [
"MedicineConfirm"
]
},
"MedicineConfirm": {
"filename": "MedicineConfirm.png",
"type": "clickSelf",
"reduceOtherTimes": [
"StartButton1"
],
"next": [
"StartButton1"
]
},
"UseStone": {
"filename": "UseStone.png",
"type": "doNothing",
"next": [
"StoneConfirm"
]
},
"StoneConfirm": {
"filename": "MedicineConfirm.png",
"type": "clickSelf",
"maxTimes": 0,
"reduceOtherTimes": [
"StartButton1"
],
"next": [
"StartButton1"
]
},
"PrtsErrorConfirm": {
"filename": "PrtsErrorConfirm.png",
"type": "doNothing",
"next": [
"AbandonAction"
]
},
"AbandonAction": {
"filename": "AbandonAction.png",
"type": "clickSelf",
"reduceOtherTimes": [
"StartButton1",
"StartButton2",
"Loading"
],
"next": [
"Random"
]
},
"VisitBegin": {
"filename": "",
"threshold": 0,
"type": "doNothing",
"next": [
"Friends",
"FriendsList",
"StartToVisit",
"VisitNext",
"VisitNextBlack",
"ReturnToFriends"
]
},
"ReturnToFriends": {
"filename": "Return.png",
"type": "clickSelf",
"next": [
"Friends",
"ReturnToFriends"
]
},
"Friends": {
"filename": "Friends.png",
"type": "clickSelf",
"next": [
"FriendsList"
]
},
"FriendsList": {
"filename": "FriendsList.png",
"type": "clickSelf",
"next": [
"StartToVisit"
]
},
"StartToVisit": {
"filename": "StartToVisit.png",
"type": "clickSelf",
"next": [
"VisitNext"
]
},
"VisitNext": {
"filename": "VisitNext.png",
"type": "clickSelf",
"threshold": 0.99,
"maxTimes": 21,
"exceededNext": [
"ReturnToMall"
],
"next": [
"VisitNext",
"VisitNextBlack"
]
},
"ReturnToMall": {
"filename": "Return.png",
"type": "clickSelf",
"next": [
"Mall",
"ReturnToMall",
"ReturnToMallConfirm"
]
},
"ReturnToMallConfirm": {
"filename": "PopupConfirm.png",
"type": "clickSelf",
"next": [
"ReturnToMall"
]
},
"Mall": {
"filename": "Mall.png",
"type": "clickSelf",
"next": [
"CreditStore"
]
},
"CreditStore": {
"filename": "CreditStore.png",
"threshold": 0.89,
"rearDelay": 1000,
"type": "clickSelf",
"next": [
"CollectCredit",
"Stop"
]
},
"CollectCredit": {
"filename": "CollectCredit.png",
"type": "clickSelf",
"next": [
"Stop"
]
},
"VisitLimited": {
"filename": "VisitLimited.png",
"type": "doNothing",
"next": [
"ReturnToMall"
]
},
"VisitNextBlack": {
"filename": "VisitNextBlack.png",
"type": "doNothing",
"next": [
"ReturnToMall"
]
},
"Stop": {
"filename": "",
"threshold": 0,
"type": "stop",
"next": []
}
}
}

2
update_resource.bat Normal file
View File

@@ -0,0 +1,2 @@
xcopy /e /y /i resource x64\Debug\resource
xcopy /e /y /i resource x64\Release\resource