Compare commits

...

116 Commits

Author SHA1 Message Date
MistEO
ab5b4dd072 update resource 2021-07-26 19:14:26 +08:00
MistEO
0908d0e381 update log 2021-07-25 22:32:16 +08:00
MistEO
2e16d76569 Update README.md 2021-07-25 22:16:41 +08:00
MistEO
0b622e1313 更新GUI,完成自动关机功能 2021-07-25 22:03:15 +08:00
MistEO
ba104a0705 优化截图裁剪,再额外多裁剪一圈 2021-07-25 21:37:49 +08:00
MistEO
3c9f41ae4b 更新界面布局 2021-07-25 16:56:49 +08:00
MistEO
8a08223ab9 新增关机按钮的GUI,功能还没做 2021-07-25 16:52:50 +08:00
MistEO
47299fec45 更新版本号beat.03 2021-07-25 16:23:17 +08:00
MistEO
b683ca52d5 update 2021-07-25 16:21:02 +08:00
MistEO
b95f1f2dc9 更新资源图片,和VS工程文件 2021-07-25 16:11:20 +08:00
MistEO
423d538a80 更新模拟器适配 2021-07-25 14:48:27 +08:00
MistEO
eb6eb55161 兼容MuMu模拟器 2021-07-25 03:02:14 +08:00
MistEO
a195f559b8 优化分辨率自适应,现在不强制调整窗口大小了 2021-07-25 00:17:53 +08:00
MistEO
b5776d33b0 添加注释 2021-07-24 19:37:14 +08:00
MistEO
63aa3575c6 update readme 2021-07-24 18:05:23 +08:00
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
77 changed files with 4265 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,34 +10,96 @@ 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}
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}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Screenshot", "Tools\Screenshot\Screenshot.vcxproj", "{4AC1CFFF-D7B8-4FDA-BCFD-E4754275979B}"
ProjectSection(ProjectDependencies) = postProject
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{6C4B8D52-51D1-45F8-AAEC-808035443FD6}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3rdPart", "3rdPart", "{402D9F27-234E-41A9-BEB1-1FC1FA3C8825}"
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
{4AC1CFFF-D7B8-4FDA-BCFD-E4754275979B}.Debug|Any CPU.ActiveCfg = Debug|Win32
{4AC1CFFF-D7B8-4FDA-BCFD-E4754275979B}.Debug|x64.ActiveCfg = Debug|x64
{4AC1CFFF-D7B8-4FDA-BCFD-E4754275979B}.Debug|x64.Build.0 = Debug|x64
{4AC1CFFF-D7B8-4FDA-BCFD-E4754275979B}.Debug|x86.ActiveCfg = Debug|Win32
{4AC1CFFF-D7B8-4FDA-BCFD-E4754275979B}.Debug|x86.Build.0 = Debug|Win32
{4AC1CFFF-D7B8-4FDA-BCFD-E4754275979B}.Release|Any CPU.ActiveCfg = Release|Win32
{4AC1CFFF-D7B8-4FDA-BCFD-E4754275979B}.Release|x64.ActiveCfg = Release|x64
{4AC1CFFF-D7B8-4FDA-BCFD-E4754275979B}.Release|x64.Build.0 = Release|x64
{4AC1CFFF-D7B8-4FDA-BCFD-E4754275979B}.Release|x86.ActiveCfg = Release|Win32
{4AC1CFFF-D7B8-4FDA-BCFD-E4754275979B}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{9CC7838E-D5FB-4771-848D-5F83D638C5AD} = {402D9F27-234E-41A9-BEB1-1FC1FA3C8825}
{36BC08F3-71CF-429A-AE69-291BE8962CB2} = {6C4B8D52-51D1-45F8-AAEC-808035443FD6}
{4AC1CFFF-D7B8-4FDA-BCFD-E4754275979B} = {6C4B8D52-51D1-45F8-AAEC-808035443FD6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4F2C0E4B-4FE9-47C6-A878-6BD2FAD8B9B2}
EndGlobalSection

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,58 @@
#pragma once
#include <thread>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <optional>
#include <unordered_map>
#include "AsstDef.h"
#include "Configer.h"
namespace cv {
class Mat;
}
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);
// pair<scale, image>
std::pair<double, cv::Mat> get_format_image();
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,156 @@
#pragma once
#include <string>
#include <unordered_map>
#include <vector>
#include <ostream>
namespace asst {
const static std::string Version = "release.beta.03";
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;
std::string display;
std::string display_regex;
int display_width = 0;
int display_height = 0;
};
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;
int right_offset = 0;
int bottom_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; // 执行了该任务后,需要减少别的任务的执行次数。例如执行了吃理智药,则说明上一次点击蓝色开始行动按钮没生效,所以蓝色开始行动要-1
asst::Rect specific_area; // 指定区域目前仅针对ClickRect任务有用会点这个区域
int pre_delay = 0; // 执行该任务前的延时
int rear_delay = 0; // 执行该任务后的延时
};
struct Options {
bool identify_cache = false; // 图像识别缓存功能开启后可以大幅降低CPU消耗但需要保证要识别的按钮每次的位置不会改变
int identify_delay = 0; // 图像识别延时越快操作越快但会增加CPU消耗
int control_delay_lower = 0; // 点击随机延时下限:每次点击操作会进行随机延时
int control_delay_upper = 0; // 点击随机延时上限:每次点击操作会进行随机延时
bool print_window = false; // 截图功能开启后每次结算界面会截图到screenshot目录下
int print_window_delay = 0; // 截图延时:每次到结算界面,掉落物品不是一次性出来的,有个动画,所以需要等一会再截图
int print_window_crop_offset = 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 image_2_hist(const cv::Mat& src);
double image_hist_comp(const cv::Mat& src, const cv::MatND& hist);
static asst::Rect cvrect_2_rect(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,110 @@
#pragma once
#include <fstream>
#include <mutex>
#include <iostream>
#include "AsstAux.h"
#include "AsstDef.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() {
log_trace("-----------------------------");
log_trace("MeoAssistance Process Start");
log_trace("Version", Version);
log_trace("Build DataTime", __DATE__, __TIME__);
log_trace("Working Path", GetCurrentDir());
log_trace("Resource Path", GetResourceDir());
log_trace("-----------------------------");
}
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,51 @@
#pragma once
#include <string>
#include <random>
#include <optional>
#include <Windows.h>
#include "AsstDef.h"
namespace cv {
class Mat;
}
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);
void setControlScale(double scale);
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();
std::optional<std::string> callCmd(const std::string& cmd, bool use_pipe = true);
const EmulatorInfo m_emulator_info;
const HandleType m_handle_type;
HWND m_handle = NULL;
bool m_is_adb = false;
std::string m_click_cmd; // adb点击命令不是adb的句柄用不到这个
std::minstd_rand m_rand_engine;
int m_width = 0;
int m_height = 0;
//int m_x_offset = 0;
//int m_y_offset = 0;
double m_control_scale = 1;
};
}

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,358 @@
#include "Assistance.h"
#include "WinMacro.h"
#include "Configer.h"
#include "Identify.h"
#include "Logger.hpp"
#include "AsstAux.h"
#include <opencv2/opencv.hpp>
#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_all();
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;
if (type == "status") {
if (param == "running") {
return std::to_string(m_thread_running);
}
else {
return std::nullopt;
}
}
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&& [scale, image] = get_format_image();
bool ret = cv::imwrite(filename.c_str(), image);
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 && [scale, cur_image] = pThis->get_format_image();
pThis->m_pCtrl->setControlScale(scale);
if (cur_image.empty()) {
DebugTraceError("Unable to capture window image!!!");
pThis->stop(false);
continue;
}
if (cur_image.rows < 100) {
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; }
}
if (!pThis->m_thread_running) {
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);
}
}
}
std::pair<double, cv::Mat> asst::Assistance::get_format_image()
{
auto && cur_image = m_pView->getImage(m_pView->getWindowRect());
if (cur_image.empty() || cur_image.cols < m_configer.DefaultWindowWidth) {
DebugTraceError("Window image error");
return { 0, std::move(cur_image) };
}
// 把模拟器边框的一圈裁剪掉。再额外裁一圈,不然企鹅物流识别不出来
auto&& window_info = m_pView->getEmulatorInfo();
int x_offset = window_info.x_offset + m_configer.m_options.print_window_crop_offset;
int y_offset = window_info.y_offset + m_configer.m_options.print_window_crop_offset;
int width = cur_image.cols - x_offset - window_info.right_offset - m_configer.m_options.print_window_crop_offset;
int height = cur_image.rows - y_offset - window_info.bottom_offset - m_configer.m_options.print_window_crop_offset;
cv::Mat cropped(cur_image, cv::Rect(x_offset, y_offset, width, height));
//// 调整尺寸,与资源中截图的标准尺寸一致
//cv::Mat dst;
//cv::resize(cropped, dst, cv::Size(m_configer.DefaultWindowWidth, m_configer.DefaultWindowHeight));
double scale_width = static_cast<double>(width) / m_configer.DefaultWindowWidth;
double scale_height = static_cast<double>(height) / m_configer.DefaultWindowHeight;
// 有些模拟器有可收缩的侧边,会增加宽度。
// config.json中设置的是侧边展开后的offset
// 如果用户把侧边收起来了,则有侧边的那头会额外裁剪掉一些,长度偏小
// 所以按这里面长、宽里大的那个算,大的那边没侧边
double scale = std::max(scale_width, scale_height);
return { scale, std::move(cropped) };
}

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,280 @@
#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)
{
DebugTraceFunction;
DebugTrace("Configer::reload | ", 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) {
DebugTrace("parse error", content);
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();
temp.m_options.print_window_crop_offset = options_obj["printWindowCropOffset"].as_integer();
}
DebugTrace("Options", options_obj.to_string());
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("adb")) {
emulator_info.is_adb = true;
// meojson的bug暂时没空修先转个字符串
emulator_info.adb.path = StringReplaceAll(emulator_json["adb"]["path"].as_string(), "\\\\", "\\");
emulator_info.adb.connect = emulator_json["adb"]["connect"].as_string();
emulator_info.adb.click = emulator_json["adb"]["click"].as_string();
emulator_info.adb.display = emulator_json["adb"]["display"].as_string();
emulator_info.adb.display_regex = emulator_json["adb"]["displayRegex"].as_string();
}
emulator_info.x_offset = emulator_json["xOffset"].as_integer();
emulator_info.y_offset = emulator_json["yOffset"].as_integer();
if (emulator_json.exist("rightOffset")) {
emulator_info.right_offset = emulator_json["rightOffset"].as_integer();
}
if (emulator_json.exist("bottomOffset")) {
emulator_info.bottom_offset = emulator_json["bottomOffset"].as_integer();
}
emulator_info.width = DefaultWindowWidth + emulator_info.x_offset + emulator_info.right_offset;
emulator_info.height = DefaultWindowHeight + emulator_info.y_offset + emulator_info.bottom_offset;
temp.m_handles.emplace(name, emulator_info);
}
}
catch (json::exception& e) {
DebugTraceError("Load config json error!", e.what());
return false;
}
*this = std::move(temp);
DebugTrace("Load config succeed");
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,110 @@
#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::image_2_hist(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(image_2_hist(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() };
}
// 有缓存用直方图比较CPU占用会低很多但要保证每次按钮图片的位置不变
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, cvrect_2_rect(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, image_2_hist(cur(raw_rect))));
}
return { AlgorithmType::MatchTemplate, value, cvrect_2_rect(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,373 @@
#include "WinMacro.h"
#include <vector>
#include <utility>
#include <algorithm>
#include <chrono>
#include <stdint.h>
#include <WinUser.h>
#include <opencv2/opencv.hpp>
#include "AsstDef.h"
#include "Logger.hpp"
#include "Configer.h"
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;
if (!callCmd(connect_cmd)) {
DebugTraceError("Connect Adb Error");
return false;
}
auto display_ret = callCmd(adb_dir + m_emulator_info.adb.display);
if (display_ret) {
std::string pipe_str = std::move(display_ret).value();
sscanf_s(pipe_str.c_str(), m_emulator_info.adb.display_regex.c_str(),
&m_emulator_info.adb.display_width, &m_emulator_info.adb.display_height);
}
else {
DebugTraceError("Get Display Error");
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;
}
}
std::optional<std::string> asst::WinMacro::callCmd(const std::string& cmd, bool use_pipe)
{
// 初始化管道
constexpr int PipeBuffSize = 1024;
HANDLE pipe_read = NULL;
HANDLE pipe_write = NULL;
SECURITY_ATTRIBUTES sa_out_pipe;
::ZeroMemory(&sa_out_pipe, sizeof(sa_out_pipe));
sa_out_pipe.nLength = sizeof(SECURITY_ATTRIBUTES);
sa_out_pipe.lpSecurityDescriptor = NULL;
sa_out_pipe.bInheritHandle = TRUE;
BOOL pipe_ret = FALSE;
if (use_pipe) {
pipe_ret = ::CreatePipe(&pipe_read, &pipe_write, &sa_out_pipe, PipeBuffSize);
DebugTrace("Create Pipe ret", pipe_ret);
}
// 准备启动ADB进程
STARTUPINFOA startup_info;
PROCESS_INFORMATION process_info;
ZeroMemory(&startup_info, sizeof(startup_info));
ZeroMemory(&process_info, sizeof(process_info));
startup_info.cb = sizeof(STARTUPINFO);
startup_info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
startup_info.hStdOutput = pipe_write;
startup_info.hStdError = pipe_write;
startup_info.wShowWindow = SW_HIDE;
DWORD ret = -1;
if (!::CreateProcessA(NULL, const_cast<LPSTR>(cmd.c_str()), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &startup_info, &process_info)) {
DebugTraceError("Create process error");
return std::nullopt;
}
::WaitForSingleObject(process_info.hProcess, 30000);
std::string pipe_str;
if (use_pipe && pipe_ret) {
DWORD read_num = 0;
DWORD std_num = 0;
if (::PeekNamedPipe(pipe_read, NULL, 0, NULL, &read_num, NULL) && read_num > 0) {
char pipe_buffer[PipeBuffSize] = { 0 };
::ReadFile(pipe_read, pipe_buffer, read_num, &std_num, NULL);
pipe_str = std::string(pipe_buffer, std_num);
}
}
::GetExitCodeProcess(process_info.hProcess, &ret);
::CloseHandle(process_info.hProcess);
::CloseHandle(process_info.hThread);
DebugTrace("Call", cmd, "ret", ret);
if (use_pipe) {
DebugTrace("Pipe:", pipe_str);
}
if (pipe_read != NULL) {
::CloseHandle(pipe_read);
}
if (pipe_write != NULL) {
::CloseHandle(pipe_write);
}
return pipe_str;
}
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;
}
int x = p.x * m_control_scale;
int y = p.y * m_control_scale;
DebugTrace("Click, raw:", p.x, p.y, "corr:", x, y);
if (m_is_adb) {
std::string cur_cmd = StringReplaceAll(m_click_cmd, "[x]", std::to_string(x));
cur_cmd = StringReplaceAll(cur_cmd, "[y]", std::to_string(y));
return callCmd(cur_cmd, false).has_value();
}
else {
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 });
}
void asst::WinMacro::setControlScale(double scale)
{
if (m_is_adb) {
m_control_scale = scale * scale * m_emulator_info.adb.display_width / Configer::DefaultWindowWidth;
}
else {
m_control_scale = scale;
}
}
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,26 @@
<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="520" Width="410" 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,300,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_startSanity"/>
<Button x:Name="button_stop" Content="停止" HorizontalAlignment="Left" Margin="50,380,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,300,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_visit"/>
<Label x:Name="exec_times" Content="" HorizontalAlignment="Left" Margin="230,60,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"/>
<CheckBox x:Name="checkBox_shutdown" Content="刷完自动关机" HorizontalAlignment="Left" Margin="50,250,0,0" VerticalAlignment="Top" Checked="checkBox_shutdown_Checked"/>
<Label x:Name="label_status" Content="" HorizontalAlignment="Left" Margin="230,30,0,0" VerticalAlignment="Top"/>
</Grid>
</Window>

View File

@@ -0,0 +1,186 @@
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 = "";
label_status.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 + " 个";
}
StringBuilder buff_running = new StringBuilder(4);
AsstGetParam(p_asst, "status", "running", buff_running, 4);
if (int.Parse(buff_running.ToString()) == 0)
{
update_times.Stop();
label_status.Content = "已刷完,自动停止";
if (checkBox_shutdown.IsChecked == true)
{
System.Diagnostics.Process.Start("shutdown.exe", "-s -t 60");
MessageBoxResult result = MessageBox.Show("已刷完,即将关机,是否取消?", "提示", MessageBoxButton.OK);
if (result == MessageBoxResult.OK)
{
System.Diagnostics.Process.Start("shutdown.exe", "-a");
}
}
}
else
{
label_status.Content = "正在运行中……";
}
}
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);
}
}
private void checkBox_shutdown_Checked(object sender, RoutedEventArgs e)
{
}
}
}

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.3.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,-656.667,0" VerticalAlignment="Top" Height="281" Width="1000" 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

144
README.md
View File

@@ -2,6 +2,146 @@
A game assistance for Arknights
一款明日方舟的游戏辅助,目前仅支持蓝叠模拟器
一款明日方舟的游戏辅助,供PC端安卓模拟器使用龟速开发中……
使用C++ WinAPI龟速开发中……
![界面截图](readme/gui.png)
## 功能介绍
- 自动刷理智
- 可设置是否吃完理智药
- 可设置是否吃石头以及数量
- 可设置刷的次数(可以用来刷剿灭)
- 可设置刷完自动关机
- 支持剿灭模式
- 支持打完升级了的情况
- 支持代理失败的情况,会自动放弃本次行动
- 支持每次刷完自动截图,可用于上传企鹅物流~
- 自动访问好友基建
- 访问完了还会贴心的帮你点进信用商店~
- 其他优势
- 所有操作,都是点击按钮内随机位置,且支持设置随机延时,没有封号风险
- 模拟器窗口可以被遮挡,即使全屏看视频、玩游戏,也不影响辅助运行(但模拟器窗口不能最小化)
- 支持多款主流模拟器
- 自适应分辨率及屏幕缩放
- 未来更多功能见[Todo](#Todo)
### 模拟器支持
#### 蓝叠模拟器
完美支持,作者绝大部分测试均在蓝叠上进行,稳定性最能保障
#### MuMu模拟器
完美支持专门单独做了一套基于adb的控制逻辑。需要关闭模拟器的底部工具栏快捷键Alt+T
#### MuMu手游助手星云引擎
不支持MuMu不响应SendMessage鼠标消息而且这个版本不支持adb控制正在想办法……
#### 逍遥模拟器
支持,需要收起右侧侧边栏后使用,未多做测试
#### 雷电模拟器
支持,需要收起右侧侧边栏后使用,未多做测试
#### 夜神模拟器
支持,效果不太好,且辅助开始后不可移动模拟器窗口,不推荐使用
#### 腾讯手游助手
不支持,腾讯不支持句柄的窗口尺寸调节,有人需要的话再单独做
#### 其他
若需要使用其他模拟器、或上述不兼容的模拟器。欢迎给我提[ISSUE](https://github.com/MistEO/MeoAssistance/issues),会根据情况尽量适配~
## 使用说明
### 基本说明
1. 使用支持的模拟器打开明日方舟
2. 解压压缩包,**使用管理员权限**,打开"MeoAsstGui.exe"
3. 注意:运行期间,模拟器窗口可以被遮挡,全屏玩游戏、看视频等,完全不影响,但是模拟器不能最小化
### 刷理智
1. 明日方舟打开**蓝色开始按钮**的界面
2. 根据你的需要勾选"吃理智药"和"吃石头"
3. 点击"开始刷理智",开始后上面的选项也可以随时修改
4. 刷完了会自动停止的
### 访问好友基建
1. 明日方舟处于任意界面均可,会自动帮你点过去
2. 点击"访问基建"
3. 达到10次上限或者所有可访问的好友都访问完了就会自动停的
4. 然后会贴心的帮你跳转到信用商店,顺便收了当天信用~
### 设置操作延时
请手动修改`resource\config.json`文件中,`options`.`controlDelayRange`字段的值,格式为`[最小延时, 最大延时]`单位为毫秒例如想设置3~5秒的随机延时即设置为`[ 3000, 5000]` 即可。文件保存后请重新打开程序。
![图例](readme/controlDelayRange.png)
### 自动截图功能
每次刷完结算界面,会自动截一张图,保存在`screenshot`文件夹中
这个功能默认是打开的,不需要的话可以手动关掉:请手动修改`resource\config.json`文件中,`options`.`printWindow`字段的值,`true`是打开,`false`是关闭。文件保存后请重新打开程序。
![图例](readme/printWindow.png)
## Todo
~~在做了在做了.jpg~~
- [ ] 功能
- [ ] 图形化界面
- [x] 基本图形化界面
- [ ] 图形化界面进一步完善
- [ ] 日志打印,错误提示
- [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>Tools</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;
}

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>{4AC1CFFF-D7B8-4FDA-BCFD-E4754275979B}</ProjectGuid>
<RootNamespace>Tools</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>Screenshot</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>

30
Tools/Screenshot/main.cpp Normal file
View File

@@ -0,0 +1,30 @@
#include "Assistance.h"
#include "AsstAux.h"
#include "Logger.hpp"
int main(int argc, char** argv)
{
using namespace asst;
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());
}
char ch = 0;
while (ch != EOF) {
ch = getchar();
auto time_str = StringReplaceAll(StringReplaceAll(GetFormatTimeString(), " ", "_"), ":", "-");
std::string filename = GetCurrentDir() + "screenshot\\" + time_str + ".png";
asst.print_window(filename);
}
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: 27 KiB

BIN
readme/printWindow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 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: 39 KiB

BIN
resource/CreditStore.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
resource/Friends.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 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: 48 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: 54 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: 40 KiB

BIN
resource/StartButton1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
resource/StartButton2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

BIN
resource/StartToVisit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 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: 29 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: 60 KiB

BIN
resource/VisitNextBlack.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

477
resource/config.json Normal file
View File

@@ -0,0 +1,477 @@
{
"version": "0.4",
"options": {
"identifyCache": true,
"identifyCache_Doc": "图像识别缓存功能开启后可以大幅降低CPU消耗但需要保证要识别的按钮每次的位置不会改变。true-开启false-关闭默认true",
"identifyDelay": 1000,
"identifyDelay_Doc": "图像识别延时越快操作越快但会增加CPU消耗。单位毫秒默认1000",
"printWindow": true,
"printWindow_Doc": "截图功能开启后每次结算界面会截图到screenshot目录下。true-开启false-关闭默认true",
"printWindowDelay": 3000,
"printWindowDelay_Doc": "截图延时每次到结算界面掉落物品不是一次性出来的有个动画所以需要等一会再截图。单位毫秒默认3000",
"printWindowCropOffset": 5,
"printWindowCropOffset_Doc": "截图额外裁剪再额外把边框裁减掉一圈不然企鹅物流有可能识别不出来。单位像素默认5",
"controlDelayRange": [
0,
0
],
"controlDelayRange_Doc": "点击随机延时:每次点击操作会进行随机延时,降低封号风险(好像也没听说过谁被封号的)。格式为 [ 最小延时, 最大延时 ]单位为毫秒。例如想设置3~5秒延时即修改为[ 3000, 5000 ]默认0~0"
},
"handle_Doc": "下面的和模拟器窗口捕获逻辑有关,不需要修改",
"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"
}
],
"xOffset": 11,
"yOffset": 46,
"rightOffset": 11,
"bottomOffset": 10
},
"Nox": {
"window": [
{
"class": "Qt5QWindowIcon",
"window": "夜神模拟器"
}
],
"view": [
{
"class": "Qt5QWindowIcon",
"window": "夜神模拟器"
}
],
"control": [
{
"class": "Qt5QWindowIcon",
"window": "夜神模拟器"
}
],
"xOffset": 2,
"yOffset": 39,
"rightOffset": 39,
"bottomOffset": 9
},
"LDPlayer": {
"window": [
{
"class": "LDPlayerMainFrame",
"window": "雷电模拟器"
}
],
"view": [
{
"class": "LDPlayerMainFrame",
"window": "雷电模拟器"
}
],
"control": [
{
"class": "LDPlayerMainFrame",
"window": "雷电模拟器"
},
{
"class": "RenderWindow",
"window": "TheRender"
}
],
"xOffset": 0,
"yOffset": 35
},
"XYAZ": {
"window": [
{
"class": "Qt5QWindowIcon",
"window": "逍遥模拟器"
}
],
"view": [
{
"class": "Qt5QWindowIcon",
"window": "逍遥模拟器"
}
],
"control": [
{
"class": "Qt5QWindowIcon",
"window": "逍遥模拟器"
},
{
"class": "Qt5QWindowIcon",
"window": "MainWindowWindow"
}
],
"xOffset": 1,
"yOffset": 48,
"rightOffset": 1,
"bottomOffset": 1
},
"Tencent": {
"window": [
{
"class": "TXGuiFoundation",
"window": "腾讯手游助手"
}
],
"view": [
{
"class": "TXGuiFoundation",
"window": "腾讯手游助手"
}
],
"control": [
{
"class": "TXGuiFoundation",
"window": "腾讯手游助手"
},
{
"class": "AEngineRenderWindowClass",
"window": "AEngineRenderWindow"
}
],
"xOffset": 1,
"yOffset": 42
},
"MuMuAsst": {
"window": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - 星云引擎"
}
],
"view": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - 星云引擎"
}
],
"control": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - 星云引擎"
}
],
"adb": {
"path": "[EmulatorPath]..\\vmonitor\\bin\\adb_server.exe",
"connect": " connect 127.0.0.1:7555",
"click": " shell input tap [x] [y]",
"display": " shell dumpsys window displays | grep init= | awk ' { print $3 } '",
"displayRegex": "cur=%dx%d"
},
"xOffset": 0,
"yOffset": 36
},
"MuMuEmulator": {
"window": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - MuMu模拟器"
}
],
"view": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - MuMu模拟器"
}
],
"control": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - MuMu模拟器"
}
],
"adb": {
"path": "[EmulatorPath]..\\vmonitor\\bin\\adb_server.exe",
"connect": " connect 127.0.0.1:7555",
"click": " shell input tap [x] [y]",
"display": " shell dumpsys window displays | grep init= | awk ' { print $3 } '",
"displayRegex": "cur=%dx%d"
},
"xOffset": 0,
"yOffset": 36,
"rightOffset": 0,
"bottomOffset": 0
}
},
"tasks_Doc": "下面的和任务队列执行逻辑有关,不需要修改",
"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",
"threshold": 0.85,
"cacheThreshold": 0.85,
"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",
"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.85,
"rearDelay": 1000,
"type": "clickSelf",
"next": [
"CollectCredit",
"Stop"
]
},
"CollectCredit": {
"filename": "CollectCredit.png",
"type": "clickSelf",
"next": [
"Stop"
]
},
"VisitLimited": {
"filename": "VisitLimited.png",
"threshold": 1,
"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