From 549463cc067bb31396d88b3ffaddde6959502d90 Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 5 Jan 2022 00:23:07 +0800 Subject: [PATCH 1/3] =?UTF-8?q?docs.=E6=9B=B4=E6=96=B0=E5=AF=B9mumu?= =?UTF-8?q?=E6=A8=A1=E6=8B=9F=E5=99=A8=E7=9A=84=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/模拟器支持.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/模拟器支持.md b/docs/模拟器支持.md index a4cd76d6c7..5340772a13 100644 --- a/docs/模拟器支持.md +++ b/docs/模拟器支持.md @@ -22,7 +22,10 @@ ## MuMu 模拟器 -支持。但在部分设备上可能莫名其妙连接出错,可尝试使用自定义连接 +支持,但是 + +- 部分设备上一直连接出错:暂时不知道是什么原因,可尝试使用自定义连接 +- 部分设备上卡在主界面无法识别,过一会提示任务出错:暂时不知道是什么原因,可能和 MuMu 的渲染方式有关,推荐换模拟器( ## MuMu 手游助手(星云引擎) @@ -46,6 +49,7 @@ ## 自定义连接 -- 下载 [ADB](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) ,将`platform-tools`文件夹解压到`MeoAsstGui.exe`的同级目录 -- 进入软件`设置`-`连接设置`,填写自定义地址(需要填写IP+端口,例如`127.0.0.1:5555`) -- **注意 :** 若是使用手机,在非`16:9`分辨率下,部分功能不稳定(但也凑合能用),尤其是基建,几乎是不可用状态,正在进一步适配中。推荐使用`16:9`分辨率,经过的测试验证最多,也最稳定。 +1. 下载 [ADB](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) ,将`platform-tools`文件夹解压到`MeoAsstGui.exe`的同级目录 +2. 进入软件`设置`-`连接设置`,填写自定义地址(需要填写IP+端口,例如`127.0.0.1:5555`) + +**注意 :** 若是使用手机,在非`16:9`分辨率下,部分功能不稳定(但也凑合能用),尤其是基建,几乎是不可用状态,正在进一步适配中。推荐使用`16:9`分辨率,经过的测试验证最多,也最稳定。 From 1213831a5f1049af9c48e41f8304394acd02d7e9 Mon Sep 17 00:00:00 2001 From: yuanyan3060 <1846865993@qq.com> Date: Wed, 5 Jan 2022 02:06:10 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20golang=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Golang/cli.go | 42 ++++ src/Golang/config.yaml | 32 +++ src/Golang/go.sum | 16 ++ src/Golang/maa/config.go | 85 ++++++++ src/Golang/maa/interface.go | 23 +++ src/Golang/maa/util.go | 40 ++++ src/Golang/maa/win.go | 389 ++++++++++++++++++++++++++++++++++++ 7 files changed, 627 insertions(+) create mode 100644 src/Golang/cli.go create mode 100644 src/Golang/config.yaml create mode 100644 src/Golang/go.sum create mode 100644 src/Golang/maa/config.go create mode 100644 src/Golang/maa/interface.go create mode 100644 src/Golang/maa/util.go create mode 100644 src/Golang/maa/win.go diff --git a/src/Golang/cli.go b/src/Golang/cli.go new file mode 100644 index 0000000000..b583b37d29 --- /dev/null +++ b/src/Golang/cli.go @@ -0,0 +1,42 @@ +package main + +import ( + "errors" + "gomma/maa" + "os" + "runtime" +) + +func main() { + dir, err := os.Getwd() + if err != nil { + return + } + config, err := maa.LoadConfig("config.yaml") + if err != nil { + if errors.Is(err, os.ErrNotExist) { + config = maa.NewConfig() + err := maa.WriteConfig("config.yaml", config) + if err != nil { + return + } + } else { + return + } + } + if runtime.GOOS == "windows" { + MaaWin, err := maa.NewMaaCliWin(dir) + if err != nil { + return + } + err = MaaWin.Run(config) + if err != nil { + return + } + err = MaaWin.RunWithCron(config) + if err != nil { + return + } + for true {} + } +} \ No newline at end of file diff --git a/src/Golang/config.yaml b/src/Golang/config.yaml new file mode 100644 index 0000000000..8c70c3b9a3 --- /dev/null +++ b/src/Golang/config.yaml @@ -0,0 +1,32 @@ +customadbaddress: "" +cron: "0 0 */2 * * *" +fight: + stage: LastBattle + medicine: 999 + stone: 0 + times: 999 +infrast: + mode: 1 + orders: + - Mfg + - Trade + - Control + - Power + - Reception + - Office + - Dorm + drones: Money + threshold: 0.3 +recruit: + max: 3 + selects: + - 3 + - 4 + - 5 + confirms: + - 3 + - 4 + - 5 + refresh: true +mall: + buy: true diff --git a/src/Golang/go.sum b/src/Golang/go.sum new file mode 100644 index 0000000000..5d56dc11e1 --- /dev/null +++ b/src/Golang/go.sum @@ -0,0 +1,16 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= +github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/src/Golang/maa/config.go b/src/Golang/maa/config.go new file mode 100644 index 0000000000..e761ef9e86 --- /dev/null +++ b/src/Golang/maa/config.go @@ -0,0 +1,85 @@ +package maa + +import ( + "gopkg.in/yaml.v2" + "io/ioutil" +) + +type Config struct { + CustomAdbAddress string + Cron string + Fight struct{ + Stage string + Medicine int + Stone int + Times int + } + Infrast struct{ + Mode int + Orders []string + Drones string + Threshold float64 + } + Recruit struct{ + Max int + Selects []int + Confirms []int + Refresh bool + Expedite bool + } + Mall struct{ + Buy bool + } +} + +func NewConfig() Config { + return Config{ + CustomAdbAddress: "", + Cron: "0 0 */2 * * *", + Fight: struct { + Stage string + Medicine int + Stone int + Times int + }{Stage: "LastBattle", Medicine: 999, Stone: 0, Times: 999}, + Infrast: struct { + Mode int + Orders []string + Drones string + Threshold float64 + }{Mode: 1, Orders:[]string{"Mfg", "Trade", "Control", "Power", "Reception", "Office", "Dorm"}, Drones: "Money", Threshold: 0.3}, + Recruit: struct { + Max int + Selects []int + Confirms []int + Refresh bool + Expedite bool + }{Max: 3, Selects: []int{3,4,5}, Confirms: []int{3,4,5}, Refresh: true, Expedite: true}, + Mall: struct{ Buy bool }{Buy: true}, + } +} + +func LoadConfig(path string) (Config, error) { + conf := Config{} + yamlFile, err := ioutil.ReadFile(path) + if err != nil { + return conf, err + } + err = yaml.Unmarshal(yamlFile, &conf) + if err != nil { + return conf, err + } + return conf, nil +} + +func WriteConfig(path string, conf Config) error { + yamlFile, err := yaml.Marshal(&conf) + if err != nil { + return err + } + err = ioutil.WriteFile(path, yamlFile, 0755) + if err != nil { + return err + } + return nil +} \ No newline at end of file diff --git a/src/Golang/maa/interface.go b/src/Golang/maa/interface.go new file mode 100644 index 0000000000..b50d037a18 --- /dev/null +++ b/src/Golang/maa/interface.go @@ -0,0 +1,23 @@ +package maa + + +type Maa interface { + CallBack(message int, details uintptr, arg uintptr) uintptr + CreateEx(arg uintptr) error + CatchDefault() error + CatchEmulator() error + CatchCustom(address string) error + AppendFight(stage string, medicine int, stone int, times int) error + AppendAward() error + AppendVisit() error + AppendMall(do bool) error + AppendInfrast(mode int, orders []string, drones string, threshold float64) error + AppendRecruit(max int, selects []int, confirms []int, refresh bool, expedite bool) error + Start() error + Stop() error + StartRecruitCalc(selects []int, times bool) error + GetVersion() (string, error) + SetPenguinId(id string) error + Run(config Config) error + RunWithCron(config Config) error +} \ No newline at end of file diff --git a/src/Golang/maa/util.go b/src/Golang/maa/util.go new file mode 100644 index 0000000000..5c50e1b745 --- /dev/null +++ b/src/Golang/maa/util.go @@ -0,0 +1,40 @@ +package maa + +import "C" +import ( + "errors" + "syscall" + "unsafe" +) + +var FalseError = errors.New("maa return false") + +func UintPtrFromString(s string) (uintptr, error) { + p, err := syscall.BytePtrFromString(s) + if err != nil { + return 0, err + } + return uintptr(unsafe.Pointer(p)), nil +} +func CharPtr2String(r uintptr) string { + if r==0{ + return "" + } + p := (*byte)(unsafe.Pointer(r)) + data := make([]byte, 0) + for *p != 0 { + data = append(data, *p) + r += unsafe.Sizeof(byte(0)) + p = (*byte)(unsafe.Pointer(r)) + } + name := string(data) + return name +} + +func UintPtrFromBool(b bool) uintptr { + if b{ + return 1 + }else { + return 0 + } +} \ No newline at end of file diff --git a/src/Golang/maa/win.go b/src/Golang/maa/win.go new file mode 100644 index 0000000000..fcab4e8daa --- /dev/null +++ b/src/Golang/maa/win.go @@ -0,0 +1,389 @@ +package maa + +import ( + "errors" + "fmt" + "github.com/robfig/cron" + log "github.com/sirupsen/logrus" + "syscall" + "unsafe" +) + +type MaaCliWin struct { + Path string + DLL *syscall.DLL + Ptr uintptr +} + +func NewMaaCliWin(path string) (*MaaCliWin, error) { + dll, err := syscall.LoadDLL(path + "/MeoAssistant.dll") + if err != nil { + return nil, err + } + maa := MaaCliWin{path, dll, 0} + err = maa.CreateEx(0) + if err != nil { + return nil, err + } + return &maa, nil +} + +func (m *MaaCliWin) CallBack(message int, details uintptr, arg uintptr) uintptr { + log.Infoln(message, CharPtr2String(details), arg) + return 0 +} + +func (m *MaaCliWin) CreateEx(arg uintptr) error { + proc, err := m.DLL.FindProc("AsstCreateEx") + if err != nil { + return err + } + a1, err := UintPtrFromString(m.Path) + if err != nil { + return err + } + a2 := syscall.NewCallback(m.CallBack) + a3 := arg + r1, _, err := proc.Call(a1, a2, a3) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn("CreateEx", err) + } + m.Ptr = r1 + return nil +} + +func (m *MaaCliWin) CatchDefault() error { + proc, err := m.DLL.FindProc("AsstCatchDefault") + if err != nil { + return err + } + r1, _, err := proc.Call(m.Ptr) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn("CatchDefault", err) + } + if r1 == 0 { + return FalseError + } + return nil +} + +func (m *MaaCliWin) CatchEmulator() error { + proc, err := m.DLL.FindProc("AsstCatchEmulator") + if err != nil { + return err + } + r1, _, err := proc.Call(m.Ptr) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn("CatchEmulator", err) + } + if r1 == 0 { + return FalseError + } + return nil +} + +// CatchCustom 没测过 +func (m *MaaCliWin) CatchCustom(address string) error { + proc, err := m.DLL.FindProc("AsstCatchCustom") + if err != nil { + return err + } + a1, err := UintPtrFromString(address) + if err != nil { + return err + } + r1, _, err := proc.Call(a1) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn("CatchCustom", err) + } + if r1 == 0 { + return FalseError + } + return nil +} + +func (m *MaaCliWin) AppendFight(stage string, medicine int, stone int, times int) error { + proc, err := m.DLL.FindProc("AsstAppendFight") + if err != nil { + return err + } + a1, err := UintPtrFromString(stage) + if err != nil { + return err + } + a2 := uintptr(medicine) + a3 := uintptr(stone) + a4 := uintptr(times) + r1, _, err := proc.Call(m.Ptr, a1, a2, a3, a4) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn("AppendFight", err) + } + if r1 == 0 { + return FalseError + } + return nil +} + +func (m *MaaCliWin) AppendAward() error { + proc, err := m.DLL.FindProc("AsstAppendAward") + if err != nil { + return err + } + r1, _, err := proc.Call(m.Ptr) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn(" AppendAward", err) + } + if r1 == 0 { + return FalseError + } + return nil +} + +func (m *MaaCliWin) AppendVisit() error { + proc, err := m.DLL.FindProc("AsstAppendVisit") + if err != nil { + return err + } + r1, _, err := proc.Call(m.Ptr) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn("AppendVisit", err) + } + if r1 == 0 { + return FalseError + } + return nil +} + +func (m *MaaCliWin) AppendMall(do bool) error { + proc, err := m.DLL.FindProc("AsstAppendMall") + if err != nil { + return err + } + a1:=UintPtrFromBool(do) + r1, _, err := proc.Call(m.Ptr, a1) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn("AppendMall", err) + } + if r1 == 0 { + return FalseError + } + return nil +} + +func (m *MaaCliWin) AppendInfrast(mode int, orders []string, drones string, threshold float64) error { + proc, err := m.DLL.FindProc("AsstAppendInfrast") + if err != nil { + return err + } + var orderArr []uintptr + for _, order := range orders { + orderStr, err := UintPtrFromString(order) + if err != nil { + return err + } + orderArr = append(orderArr, orderStr) + } + if orderArr == nil { + return errors.New("orders is empty") + } + a1 := uintptr(mode) + a2 := uintptr(unsafe.Pointer(&orderArr[0])) + a3 := uintptr(len(orders)) + a4 := uintptr(unsafe.Pointer(&[]byte(drones)[0])) + a5 := uintptr(*(*uint64)(unsafe.Pointer(&threshold))) + r1, _, err := proc.Call(m.Ptr, a1, a2, a3, a4, a5) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn("AppendInfrast", err) + } + if r1 == 0 { + return FalseError + } + return nil +} + +func (m *MaaCliWin) AppendRecruit(max int, selects []int, confirms []int, refresh bool, expedite bool) error { + proc, err := m.DLL.FindProc("AsstAppendRecruit") + if err != nil { + return err + } + a1 := uintptr(max) + a2 := uintptr(unsafe.Pointer(&selects[0])) + a3 := uintptr(len(selects)) + a4 := uintptr(unsafe.Pointer(&confirms[0])) + a5 := uintptr(len(confirms)) + a6:=UintPtrFromBool(refresh) + a7:=UintPtrFromBool(expedite) + r1, _, err := proc.Call(m.Ptr, a1, a2, a3, a4, a5, a6, a7) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn("AppendRecruit", err) + } + if r1 == 0 { + return FalseError + } + return nil +} + +func (m *MaaCliWin) Start() error { + proc, err := m.DLL.FindProc("AsstStart") + if err != nil { + return err + } + r1, _, err := proc.Call(m.Ptr) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn("Start", err) + } + if r1 == 0 { + return FalseError + } + return nil +} + +func (m *MaaCliWin) Stop() error { + proc, err := m.DLL.FindProc("AsstStop") + if err != nil { + return err + } + r1, _, err := proc.Call(m.Ptr) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn("Stop", err) + } + if r1 == 0 { + return FalseError + } + return nil +} +func (m *MaaCliWin) StartRecruitCalc(selects []int, times bool) error { + proc, err := m.DLL.FindProc("AsstStartRecruitCalc") + if err != nil { + return err + } + a1 := uintptr(unsafe.Pointer(&selects[0])) + a2:=UintPtrFromBool(times) + r1, _, err := proc.Call(m.Ptr, a1, a2) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn("StartRecruitCalc", err) + } + if r1 == 0 { + return FalseError + } + return nil +} + +func (m *MaaCliWin) GetVersion() (string, error) { + proc, err := m.DLL.FindProc("AsstGetVersion") + if err != nil { + return "", err + } + r1, _, err := proc.Call(m.Ptr) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn("GetVersion", err) + } + if r1 == 0 { + return "", FalseError + } + return CharPtr2String(r1), nil +} + +func (m *MaaCliWin) SetPenguinId(id string) error { + proc, err := m.DLL.FindProc("AsstSetPenguinId") + if err != nil { + return err + } + a1, err := UintPtrFromString(id) + if err != nil { + return err + } + r1, _, err := proc.Call(m.Ptr, a1) + if !errors.Is(err, syscall.Errno(0)) { + log.Warn("SetPenguinId", err) + } + if r1 == 0 { + return FalseError + } + return nil +} +func (m *MaaCliWin) Run(config Config) error { + version, err := m.GetVersion() + if err != nil { + return err + } + log.Infoln("DLL版本:", version) + // 连接模拟器 + if config.CustomAdbAddress != "" { + err := m.CatchCustom(config.CustomAdbAddress) + log.Infoln("连接自定义模拟器", config.CustomAdbAddress) + if err != nil { + log.Error("连接自定义模拟器失败", err) + return err + } + } else { + err := m.CatchDefault() + log.Infoln("连接默认模拟器", config.CustomAdbAddress) + if err != nil { + log.Error("连接默认模拟器失败", err) + return err + } + } + // 添加战斗任务 + fight := config.Fight + err = m.AppendFight(fight.Stage, fight.Medicine, fight.Stone, fight.Times) + if err != nil { + return err + } + log.Println("添加战斗任务") + // 添加基建任务 + infrast := config.Infrast + err = m.AppendInfrast(infrast.Mode, infrast.Orders, infrast.Drones, infrast.Threshold) + if err != nil { + return err + } + log.Println("添加基建任务") + // 添加公招任务 + recruit := config.Recruit + err = m.AppendRecruit(recruit.Max, recruit.Selects, recruit.Confirms, recruit.Refresh, recruit.Expedite) + if err != nil { + return err + } + log.Println("添加公招任务") + // 添加访问好友任务 + err = m.AppendVisit() + if err != nil { + return err + } + log.Println("添加访问好友任务") + // 添加商店任务 + err = m.AppendMall(config.Mall.Buy) + if err != nil { + return err + } + log.Println("添加商店任务") + // 添加领取任务奖励任务 + err = m.AppendAward() + log.Println("添加领取奖励任务") + if err != nil { + return err + } + err = m.Start() + log.Println("开始执行任务") + if err != nil { + return err + } + return nil +} +func (m *MaaCliWin) RunWithCron(config Config) error { + c := cron.New() // 新建一个定时任务对象 + err := c.AddFunc(config.Cron, func() { + log.Println(config.Cron, "定时任务开始执行") + err := m.Run(config) + if err != nil { + return + } + }) + if err != nil { + fmt.Println(err) + return err + } + c.Start() + log.Infoln("设置定时任务") + return nil +} From 994e4395c229828f35ba826ddf4572e7ba4ab543 Mon Sep 17 00:00:00 2001 From: yuanyan3060 <1846865993@qq.com> Date: Wed, 5 Jan 2022 03:49:13 +0800 Subject: [PATCH 3/3] fix a bug --- src/Golang/maa/win.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Golang/maa/win.go b/src/Golang/maa/win.go index fcab4e8daa..d749695ade 100644 --- a/src/Golang/maa/win.go +++ b/src/Golang/maa/win.go @@ -92,7 +92,7 @@ func (m *MaaCliWin) CatchCustom(address string) error { if err != nil { return err } - r1, _, err := proc.Call(a1) + r1, _, err := proc.Call(m.Ptr, a1) if !errors.Is(err, syscall.Errno(0)) { log.Warn("CatchCustom", err) }