From 1eb1c3c17f089002403dea2238cfbd90d1c0935a Mon Sep 17 00:00:00 2001 From: dongwlin Date: Thu, 19 Sep 2024 10:02:50 +0800 Subject: [PATCH 01/35] feat: add ToInts function for Rect --- internal/buffer/rect_buffer.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/buffer/rect_buffer.go b/internal/buffer/rect_buffer.go index aee8fe6..0300d94 100644 --- a/internal/buffer/rect_buffer.go +++ b/internal/buffer/rect_buffer.go @@ -13,6 +13,10 @@ type Rect struct { X, Y, W, H int32 } +func (r Rect) ToInts() [4]int32 { + return [4]int32{r.X, r.Y, r.W, r.H} +} + type RectBuffer struct { handle *C.MaaRect } From 6a9a41c8cf86072ffed8c9c03c0ddfde0eb135de Mon Sep 17 00:00:00 2001 From: dongwlin Date: Thu, 19 Sep 2024 10:19:27 +0800 Subject: [PATCH 02/35] refactor: rename `recognizer` to `recognition` --- README.md | 14 ++++---- README_zh.md | 8 ++--- custom_recognizer.go => custom_recognition.go | 34 +++++++++---------- .../main.go | 6 ++-- .../resource/image/.gitkeep | 0 .../resource/model/ocr/.gitkeep | 0 .../resource/pipeline/pipeline.json | 0 resource.go | 30 ++++++++-------- toolkit.go | 14 ++++---- 9 files changed, 53 insertions(+), 53 deletions(-) rename custom_recognizer.go => custom_recognition.go (71%) rename examples/{custom-recognizer => custom-recognition}/main.go (87%) rename examples/{custom-recognizer => custom-recognition}/resource/image/.gitkeep (100%) rename examples/{custom-recognizer => custom-recognition}/resource/model/ocr/.gitkeep (100%) rename examples/{custom-recognizer => custom-recognition}/resource/pipeline/pipeline.json (100%) diff --git a/README.md b/README.md index 2bc0e95..114127f 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ Replace `[path to maafw include directory]` with the actual path to the MaaFrame ## Examples - [Quirk Start](#quirk-start) -- [Custom Recognizer](#custom-recognizer) +- [Custom Recognition](#custom-recognition) - [Custom Action](#custom-action) - [PI CLI](#pi-cli) @@ -151,11 +151,11 @@ func main() { ``` -### Custom Recognizer +### Custom Recognition -See [custom-recognizer](examples/custom-recognizer) for details. +See [custom-recognition](examples/custom-recognition) for details. -Here is a basic example to implement your custom recognizer: +Here is a basic example to implement your custom recognition: ```go package main @@ -195,7 +195,7 @@ func main() { os.Exit(1) } - res.RegisterCustomRecognizer("MyRec", &MyRec{}) + res.RegisterCustomRecognition("MyRec", &MyRec{}) detail := tasker.PostPipeline("Startup").Wait().GetDetail() fmt.Println(detail) @@ -203,7 +203,7 @@ func main() { type MyRec struct{} -func (r *MyRec) Run(ctx *maa.Context, arg *maa.CustomRecognizerArg) (maa.CustomRecognizerResult, bool) { +func (r *MyRec) Run(ctx *maa.Context, arg *maa.CustomRecognitionArg) (maa.CustomRecognitionResult, bool) { ctx.RunRecognition("MyCustomOCR", arg.Img, maa.J{ "MyCustomOCR": maa.J{ "roi": []int{100, 100, 200, 300}, @@ -229,7 +229,7 @@ func (r *MyRec) Run(ctx *maa.Context, arg *maa.CustomRecognizerArg) (maa.CustomR ctx.OverrideNext(arg.CurrentTaskName, []string{"TaskA", "TaskB"}) - return maa.CustomRecognizerResult{ + return maa.CustomRecognitionResult{ Box: maa.Rect{0, 0, 100, 100}, Detail: "Hello World!", }, true diff --git a/README_zh.md b/README_zh.md index cdc4cf7..aba7253 100644 --- a/README_zh.md +++ b/README_zh.md @@ -152,7 +152,7 @@ func main() { ### 自定义识别器 -有关详细信息,请参阅 [custom-recognizer](examples/custom-recognizer)。 +有关详细信息,请参阅 [custom-recognition](examples/custom-recognition)。 以下是一个实现自定义识别器的基本示例: @@ -194,7 +194,7 @@ func main() { os.Exit(1) } - res.RegisterCustomRecognizer("MyRec", &MyRec{}) + res.RegisterCustomRecognition("MyRec", &MyRec{}) detail := tasker.PostPipeline("Startup").Wait().GetDetail() fmt.Println(detail) @@ -202,7 +202,7 @@ func main() { type MyRec struct{} -func (r *MyRec) Run(ctx *maa.Context, arg *maa.CustomRecognizerArg) (maa.CustomRecognizerResult, bool) { +func (r *MyRec) Run(ctx *maa.Context, arg *maa.CustomRecognitionArg) (maa.CustomRecognitionResult, bool) { ctx.RunRecognition("MyCustomOCR", arg.Img, maa.J{ "MyCustomOCR": maa.J{ "roi": []int{100, 100, 200, 300}, @@ -228,7 +228,7 @@ func (r *MyRec) Run(ctx *maa.Context, arg *maa.CustomRecognizerArg) (maa.CustomR ctx.OverrideNext(arg.CurrentTaskName, []string{"TaskA", "TaskB"}) - return maa.CustomRecognizerResult{ + return maa.CustomRecognitionResult{ Box: maa.Rect{0, 0, 100, 100}, Detail: "Hello World!", }, true diff --git a/custom_recognizer.go b/custom_recognition.go similarity index 71% rename from custom_recognizer.go rename to custom_recognition.go index 24a3b55..8970b8a 100644 --- a/custom_recognizer.go +++ b/custom_recognition.go @@ -5,7 +5,7 @@ package maa #include #include "def.h" -extern uint8_t _MaaCustomRecognizerCallbackAgent( +extern uint8_t _MaaCustomRecognitionCallbackAgent( MaaContext* ctx, int64_t task_id, const char* current_task_name, @@ -26,25 +26,25 @@ import ( ) var ( - customRecognizerCallbackID uint64 - customRecognizerCallbackAgents = make(map[uint64]CustomRecognizer) + customRecognitionCallbackID uint64 + customRecognitionCallbackAgents = make(map[uint64]CustomRecognition) ) -func registerCustomRecognizer(recognizer CustomRecognizer) uint64 { - id := atomic.AddUint64(&customRecognizerCallbackID, 1) - customRecognizerCallbackAgents[id] = recognizer +func registerCustomRecognition(recognizer CustomRecognition) uint64 { + id := atomic.AddUint64(&customRecognitionCallbackID, 1) + customRecognitionCallbackAgents[id] = recognizer return id } -func unregisterCustomRecognizer(id uint64) bool { - if _, ok := customRecognizerCallbackAgents[id]; !ok { +func unregisterCustomRecognition(id uint64) bool { + if _, ok := customRecognitionCallbackAgents[id]; !ok { return false } - delete(customRecognizerCallbackAgents, id) + delete(customRecognitionCallbackAgents, id) return true } -type CustomRecognizerArg struct { +type CustomRecognitionArg struct { TaskDetail *TaskDetail CurrentTaskName string CustomRecognizerName string @@ -53,17 +53,17 @@ type CustomRecognizerArg struct { Roi Rect } -type CustomRecognizer interface { - Run(ctx *Context, arg *CustomRecognizerArg) (CustomRecognizerResult, bool) +type CustomRecognition interface { + Run(ctx *Context, arg *CustomRecognitionArg) (CustomRecognitionResult, bool) } -type CustomRecognizerResult struct { +type CustomRecognitionResult struct { Box Rect Detail string } -//export _MaaCustomRecognizerCallbackAgent -func _MaaCustomRecognizerCallbackAgent( +//export _MaaCustomRecognitionCallbackAgent +func _MaaCustomRecognitionCallbackAgent( ctx *C.MaaContext, taskId C.int64_t, currentTaskName, customRecognizerName, customRecognitionParam C.StringView, @@ -76,7 +76,7 @@ func _MaaCustomRecognizerCallbackAgent( // Here, we are simply passing the uint64 value as a pointer // and will not actually dereference this pointer. id := uint64(uintptr(recognizerArg)) - recognizer := customRecognizerCallbackAgents[id] + recognizer := customRecognitionCallbackAgents[id] context := Context{handle: ctx} tasker := context.GetTasker() taskDetail := tasker.getTaskDetail(int64(taskId)) @@ -85,7 +85,7 @@ func _MaaCustomRecognizerCallbackAgent( ret, ok := recognizer.Run( &Context{handle: ctx}, - &CustomRecognizerArg{ + &CustomRecognitionArg{ TaskDetail: taskDetail, CurrentTaskName: C.GoString(currentTaskName), CustomRecognizerName: C.GoString(customRecognizerName), diff --git a/examples/custom-recognizer/main.go b/examples/custom-recognition/main.go similarity index 87% rename from examples/custom-recognizer/main.go rename to examples/custom-recognition/main.go index e6989dd..1295b4f 100644 --- a/examples/custom-recognizer/main.go +++ b/examples/custom-recognition/main.go @@ -35,7 +35,7 @@ func main() { os.Exit(1) } - res.RegisterCustomRecognizer("MyRec", &MyRec{}) + res.RegisterCustomRecognition("MyRec", &MyRec{}) detail := tasker.PostPipeline("Startup").Wait().GetDetail() fmt.Println(detail) @@ -43,7 +43,7 @@ func main() { type MyRec struct{} -func (r *MyRec) Run(ctx *maa.Context, arg *maa.CustomRecognizerArg) (maa.CustomRecognizerResult, bool) { +func (r *MyRec) Run(ctx *maa.Context, arg *maa.CustomRecognitionArg) (maa.CustomRecognitionResult, bool) { ctx.RunRecognition("MyCustomOCR", arg.Img, maa.J{ "MyCustomOCR": maa.J{ "roi": []int{100, 100, 200, 300}, @@ -69,7 +69,7 @@ func (r *MyRec) Run(ctx *maa.Context, arg *maa.CustomRecognizerArg) (maa.CustomR ctx.OverrideNext(arg.CurrentTaskName, []string{"TaskA", "TaskB"}) - return maa.CustomRecognizerResult{ + return maa.CustomRecognitionResult{ Box: maa.Rect{0, 0, 100, 100}, Detail: "Hello World!", }, true diff --git a/examples/custom-recognizer/resource/image/.gitkeep b/examples/custom-recognition/resource/image/.gitkeep similarity index 100% rename from examples/custom-recognizer/resource/image/.gitkeep rename to examples/custom-recognition/resource/image/.gitkeep diff --git a/examples/custom-recognizer/resource/model/ocr/.gitkeep b/examples/custom-recognition/resource/model/ocr/.gitkeep similarity index 100% rename from examples/custom-recognizer/resource/model/ocr/.gitkeep rename to examples/custom-recognition/resource/model/ocr/.gitkeep diff --git a/examples/custom-recognizer/resource/pipeline/pipeline.json b/examples/custom-recognition/resource/pipeline/pipeline.json similarity index 100% rename from examples/custom-recognizer/resource/pipeline/pipeline.json rename to examples/custom-recognition/resource/pipeline/pipeline.json diff --git a/resource.go b/resource.go index ca62080..6cb4970 100644 --- a/resource.go +++ b/resource.go @@ -6,7 +6,7 @@ package maa extern void _MaaNotificationCallbackAgent(const char* message, const char* details_json, void* callback_arg); -extern uint8_t _MaaCustomRecognizerCallbackAgent( +extern uint8_t _MaaCustomRecognitionCallbackAgent( MaaContext* ctx, int64_t task_id, const char* current_task_name, @@ -82,12 +82,12 @@ func (r *Resource) Handle() unsafe.Pointer { return unsafe.Pointer(r.handle) } -// RegisterCustomRecognizer registers a custom recognizer to the resource. -func (r *Resource) RegisterCustomRecognizer(name string, recognizer CustomRecognizer) bool { - id := registerCustomRecognizer(recognizer) +// RegisterCustomRecognition registers a custom recognition to the resource. +func (r *Resource) RegisterCustomRecognition(name string, recognition CustomRecognition) bool { + id := registerCustomRecognition(recognition) value := resourceStore.Get(r.Handle()) if oldID, ok := value.CustomRecognizersCallbackID[name]; ok { - unregisterCustomRecognizer(oldID) + unregisterCustomRecognition(oldID) } value.CustomRecognizersCallbackID[name] = id resourceStore.Set(r.Handle(), value) @@ -95,10 +95,10 @@ func (r *Resource) RegisterCustomRecognizer(name string, recognizer CustomRecogn cName := C.CString(name) defer C.free(unsafe.Pointer(cName)) - got := C.MaaResourceRegisterCustomRecognizer( + got := C.MaaResourceRegisterCustomRecognition( r.handle, cName, - C.MaaCustomRecognizerCallback(C._MaaCustomRecognizerCallbackAgent), + C.MaaCustomRecognitionCallback(C._MaaCustomRecognitionCallbackAgent), // Here, we are simply passing the uint64 value as a pointer // and will not actually dereference this pointer. unsafe.Pointer(uintptr(id)), @@ -106,11 +106,11 @@ func (r *Resource) RegisterCustomRecognizer(name string, recognizer CustomRecogn return got != 0 } -// UnregisterCustomRecognizer unregisters a custom recognizer from the resource. -func (r *Resource) UnregisterCustomRecognizer(name string) bool { +// UnregisterCustomRecognition unregisters a custom recognition from the resource. +func (r *Resource) UnregisterCustomRecognition(name string) bool { value := resourceStore.Get(r.Handle()) if id, ok := value.CustomRecognizersCallbackID[name]; ok { - unregisterCustomRecognizer(id) + unregisterCustomRecognition(id) } else { return false } @@ -118,18 +118,18 @@ func (r *Resource) UnregisterCustomRecognizer(name string) bool { cName := C.CString(name) defer C.free(unsafe.Pointer(cName)) - got := C.MaaResourceUnregisterCustomRecognizer(r.handle, cName) + got := C.MaaResourceUnregisterCustomRecognition(r.handle, cName) return got != 0 } -// ClearCustomRecognizer clears all custom recognizers registered from the resource. -func (r *Resource) ClearCustomRecognizer() bool { +// ClearCustomRecognition clears all custom recognitions registered from the resource. +func (r *Resource) ClearCustomRecognition() bool { value := resourceStore.Get(r.Handle()) for _, id := range value.CustomRecognizersCallbackID { - unregisterCustomRecognizer(id) + unregisterCustomRecognition(id) } - got := C.MaaResourceClearCustomRecognizer(r.handle) + got := C.MaaResourceClearCustomRecognition(r.handle) return got != 0 } diff --git a/toolkit.go b/toolkit.go index 693c139..afc6dc9 100644 --- a/toolkit.go +++ b/toolkit.go @@ -4,7 +4,7 @@ package maa #include #include -extern uint8_t _MaaCustomRecognizerCallbackAgent( +extern uint8_t _MaaCustomRecognitionCallbackAgent( MaaContext* ctx, int64_t task_id, const char* current_task_name, @@ -138,9 +138,9 @@ type piStoreValue struct { var piStore = make(map[uint64]piStoreValue) -// RegisterPICustomRecognizer registers a custom recognizer. -func (t *Toolkit) RegisterPICustomRecognizer(instId uint64, name string, recognizer CustomRecognizer) { - id := registerCustomRecognizer(recognizer) +// RegisterPICustomRecognition registers a custom recognizer. +func (t *Toolkit) RegisterPICustomRecognition(instId uint64, name string, recognition CustomRecognition) { + id := registerCustomRecognition(recognition) if _, ok := piStore[instId]; !ok { piStore[instId] = piStoreValue{ CustomRecognizersCallbackID: make(map[string]uint64), @@ -155,7 +155,7 @@ func (t *Toolkit) RegisterPICustomRecognizer(instId uint64, name string, recogni C.MaaToolkitProjectInterfaceRegisterCustomRecognition( C.uint64_t(instId), cName, - C.MaaCustomRecognizerCallback(C._MaaCustomRecognizerCallbackAgent), + C.MaaCustomRecognitionCallback(C._MaaCustomRecognitionCallbackAgent), // Here, we are simply passing the uint64 value as a pointer // and will not actually dereference this pointer. unsafe.Pointer(uintptr(id)), @@ -186,11 +186,11 @@ func (t *Toolkit) RegisterPICustomAction(instId uint64, name string, action Cust ) } -// ClearPICustom unregisters all custom recognizers and actions for a given instance. +// ClearPICustom unregisters all custom recognitions and actions for a given instance. func (t *Toolkit) ClearPICustom(instId uint64) { value := piStore[instId] for _, id := range value.CustomRecognizersCallbackID { - unregisterCustomRecognizer(id) + unregisterCustomRecognition(id) } for _, id := range value.CustomActionsCallbackID { unregisterCustomAction(id) From 60bd608241fba57d50cb7c20dedfd2eba0f2e7b2 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Thu, 19 Sep 2024 10:23:50 +0800 Subject: [PATCH 03/35] refactor: rename `DebugMessage` to `DebugMode` --- option.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/option.go b/option.go index c380991..4bfc3c6 100644 --- a/option.go +++ b/option.go @@ -40,10 +40,10 @@ const ( // value: bool, eg: true; val_size: sizeof(bool) GlobalOptionShowHitDraw - // GlobalOptionDebugMessage Whether to callback debug message + // GlobalOptionDebugMode Whether to debug // // value: bool, eg: true; val_size: sizeof(bool) - GlobalOptionDebugMessage + GlobalOptionDebugMode ) // SetLogDir sets the log directory. @@ -99,11 +99,11 @@ func SetShowHitDraw(enabled bool) bool { return C.MaaSetGlobalOption(C.int32_t(GlobalOptionShowHitDraw), C.MaaOptionValue(unsafe.Pointer(&cEnabled)), C.uint64_t(unsafe.Sizeof(cEnabled))) != 0 } -// SetDebugMessage sets whether to callback debug message. -func SetDebugMessage(enabled bool) bool { +// SetDebugMode sets whether to enable debug mode. +func SetDebugMode(enabled bool) bool { var cEnabled uint8 if enabled { cEnabled = 1 } - return C.MaaSetGlobalOption(C.int32_t(GlobalOptionDebugMessage), C.MaaOptionValue(unsafe.Pointer(&cEnabled)), C.uint64_t(unsafe.Sizeof(cEnabled))) != 0 + return C.MaaSetGlobalOption(C.int32_t(GlobalOptionDebugMode), C.MaaOptionValue(unsafe.Pointer(&cEnabled)), C.uint64_t(unsafe.Sizeof(cEnabled))) != 0 } From f693b6d079028298e2bb80dd346be1c3d177c200 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Fri, 20 Sep 2024 10:02:15 +0800 Subject: [PATCH 04/35] refactor: notification --- controller.go | 23 ++-- internal/notification/cgo.go | 10 -- internal/notification/notification.go | 41 ------ json.go | 8 ++ notification.go | 185 ++++++++++++++++++++++++++ resource.go | 7 +- tasker.go | 7 +- toolkit.go | 5 +- 8 files changed, 212 insertions(+), 74 deletions(-) delete mode 100644 internal/notification/cgo.go delete mode 100644 internal/notification/notification.go create mode 100644 notification.go diff --git a/controller.go b/controller.go index 7e4752d..8336eb4 100644 --- a/controller.go +++ b/controller.go @@ -9,7 +9,6 @@ extern void _MaaNotificationCallbackAgent(const char* message, const char* detai import "C" import ( "github.com/MaaXYZ/maa-framework-go/internal/buffer" - "github.com/MaaXYZ/maa-framework-go/internal/notification" "github.com/MaaXYZ/maa-framework-go/internal/store" "image" "unsafe" @@ -99,7 +98,7 @@ func NewAdbController( screencapMethod AdbScreencapMethod, inputMethod AdbInputMethod, config, agentPath string, - callback func(msg, detailsJson string), + notify Notification, ) Controller { cAdbPath := C.CString(adbPath) cAddress := C.CString(address) @@ -112,7 +111,7 @@ func NewAdbController( C.free(unsafe.Pointer(cAgentPath)) }() - id := notification.RegisterCallback(callback) + id := registerNotificationCallback(notify) handle := C.MaaAdbControllerCreate( cAdbPath, cAddress, @@ -164,9 +163,9 @@ func NewWin32Controller( hWnd unsafe.Pointer, screencapMethod Win32ScreencapMethod, inputMethod Win32InputMethod, - callback func(msg, detailsJson string), + notify Notification, ) Controller { - id := notification.RegisterCallback(callback) + id := registerNotificationCallback(notify) handle := C.MaaWin32ControllerCreate( hWnd, C.uint64_t(screencapMethod), @@ -202,7 +201,7 @@ func NewDbgController( readPath, writePath string, dbgCtrlType DbgControllerType, config string, - callback func(msg, detailsJson string), + notify Notification, ) Controller { cReadPath := C.CString(readPath) cWritePath := C.CString(writePath) @@ -213,7 +212,7 @@ func NewDbgController( C.free(unsafe.Pointer(cConfig)) }() - id := notification.RegisterCallback(callback) + id := registerNotificationCallback(notify) handle := C.MaaDbgControllerCreate( cReadPath, cWritePath, @@ -236,10 +235,10 @@ func NewDbgController( // NewCustomController creates a custom controller instance. func NewCustomController( ctrl CustomController, - callback func(msg, detailsJson string), + notify Notification, ) Controller { ctrlID := registerCustomControllerCallbacks(ctrl) - cbID := notification.RegisterCallback(callback) + notifyID := registerNotificationCallback(notify) handle := C.MaaCustomControllerCreate( (*C.MaaCustomControllerCallbacks)(ctrl.Handle()), // Here, we are simply passing the uint64 value as a pointer @@ -248,13 +247,13 @@ func NewCustomController( C.MaaNotificationCallback(C._MaaNotificationCallbackAgent), // Here, we are simply passing the uint64 value as a pointer // and will not actually dereference this pointer. - unsafe.Pointer(uintptr(cbID)), + unsafe.Pointer(uintptr(notifyID)), ) if handle == nil { return nil } controllerStore.Set(unsafe.Pointer(handle), controllerStoreValue{ - NotificationCallbackID: cbID, + NotificationCallbackID: notifyID, CustomControllerCallbacksID: ctrlID, }) return &controller{handle: handle} @@ -263,7 +262,7 @@ func NewCustomController( // Destroy frees the controller instance. func (c *controller) Destroy() { value := controllerStore.Get(c.Handle()) - notification.UnregisterCallback(value.NotificationCallbackID) + unregisterNotificationCallback(value.NotificationCallbackID) unregisterCustomControllerCallbacks(value.CustomControllerCallbacksID) controllerStore.Del(c.Handle()) C.MaaControllerDestroy(c.handle) diff --git a/internal/notification/cgo.go b/internal/notification/cgo.go deleted file mode 100644 index c520cf6..0000000 --- a/internal/notification/cgo.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !customenv - -package notification - -/* -#cgo !windows pkg-config: maa -#cgo windows CFLAGS: -IC:/maa/include -#cgo windows LDFLAGS: -LC:/maa/bin -lMaaFramework -*/ -import "C" diff --git a/internal/notification/notification.go b/internal/notification/notification.go deleted file mode 100644 index 56e2411..0000000 --- a/internal/notification/notification.go +++ /dev/null @@ -1,41 +0,0 @@ -package notification - -/* -#include - -typedef const char* StringView; - -extern void _MaaNotificationCallbackAgent(const char* message, const char* details_json, void* callback_arg); -*/ -import "C" -import ( - "sync/atomic" - "unsafe" -) - -var ( - notificationCallbackID uint64 - notificationCallbackAgents = make(map[uint64]func(msg, detailsJson string)) -) - -func RegisterCallback(callback func(msg, detailsJson string)) uint64 { - id := atomic.AddUint64(¬ificationCallbackID, 1) - notificationCallbackAgents[id] = callback - return id -} - -func UnregisterCallback(id uint64) { - delete(notificationCallbackAgents, id) -} - -//export _MaaNotificationCallbackAgent -func _MaaNotificationCallbackAgent(msg, detailsJson C.StringView, callbackArg unsafe.Pointer) { - // Here, we are simply passing the uint64 value as a pointer - // and will not actually dereference this pointer. - id := uint64(uintptr(callbackArg)) - callback := notificationCallbackAgents[id] - if callback == nil { - return - } - callback(C.GoString(msg), C.GoString(detailsJson)) -} diff --git a/json.go b/json.go index 3cee1e0..2a5a54d 100644 --- a/json.go +++ b/json.go @@ -13,3 +13,11 @@ func toJSON(v any) (string, error) { } return string(data), nil } + +func formJSON(data []byte, v any) error { + err := json.Unmarshal(data, v) + if err != nil { + return err + } + return nil +} diff --git a/notification.go b/notification.go new file mode 100644 index 0000000..959835b --- /dev/null +++ b/notification.go @@ -0,0 +1,185 @@ +package maa + +/* +#include + +typedef const char* StringView; + +extern void _MaaNotificationCallbackAgent(const char* message, const char* details_json, void* notify_arg); +*/ +import "C" +import ( + "strings" + "sync/atomic" + "unsafe" +) + +var ( + notificationCallbackID uint64 + notificationCallbackAgents = make(map[uint64]Notification) +) + +func registerNotificationCallback(notify Notification) uint64 { + id := atomic.AddUint64(¬ificationCallbackID, 1) + notificationCallbackAgents[id] = notify + return id +} + +func unregisterNotificationCallback(id uint64) { + delete(notificationCallbackAgents, id) +} + +type NotificationType int + +// NotificationType +const ( + NotificationTypeUnknown NotificationType = iota + NotificationTypeStarting + NotificationTypeSucceeded + NotificationTypeFailed +) + +type ResourceLoadingDetail struct { + ResID uint64 `json:"res_id"` + Hash string `json:"hash"` + Path string `json:"path"` +} + +type ControllerActionDetail struct { + CtrlID uint64 `json:"ctrl_id"` + UUID string `json:"uuid"` + Action string `json:"action"` +} + +type TaskerTaskDetail struct { + TaskID uint64 `json:"task_id"` + Entry string `json:"entry"` + UUID string `json:"uuid"` + Hash string `json:"hash"` +} + +type TaskNextListDetail struct { + TaskID uint64 `json:"task_id"` + Name string `json:"name"` + NextList []string `json:"next_list"` +} + +type TaskRecognitionDetail struct { + TaskID uint64 `json:"task_id"` + RecID uint64 `json:"reco_id"` + Name string `json:"name"` +} + +type TaskActionDetail struct { + TaskID uint64 `json:"task_id"` + NodeID uint64 `json:"node_id"` + Name string `json:"name"` +} + +type Notification interface { + OnResourceLoading(notifyType NotificationType, detail ResourceLoadingDetail) + OnControllerAction(notifyType NotificationType, detail ControllerActionDetail) + OnTaskerTask(notifyType NotificationType, detail TaskerTaskDetail) + OnTaskNextList(notifyType NotificationType, detail TaskNextListDetail) + OnTaskRecognition(notifyType NotificationType, detail TaskRecognitionDetail) + OnTaskAction(notifyType NotificationType, detail TaskActionDetail) + OnRawNotification(msg, detailsJSON string) + OnUnknownNotification(msg, detailsJSON string) +} + +type NotificationHandler struct{} + +func _NewNotificationHandler() Notification { + return &NotificationHandler{} +} + +func (n *NotificationHandler) OnResourceLoading(_ NotificationType, _ ResourceLoadingDetail) { + // DO NOTHING +} + +func (n *NotificationHandler) OnControllerAction(_ NotificationType, _ ControllerActionDetail) { + // DO NOTHING +} + +func (n *NotificationHandler) OnTaskerTask(_ NotificationType, _ TaskerTaskDetail) { + // DO NOTHING +} + +func (n *NotificationHandler) OnTaskNextList(_ NotificationType, _ TaskNextListDetail) { + // DO NOTHING +} + +func (n *NotificationHandler) OnTaskRecognition(_ NotificationType, _ TaskRecognitionDetail) { + // DO NOTHING +} + +func (n *NotificationHandler) OnTaskAction(_ NotificationType, _ TaskActionDetail) { + // DO NOTHING +} + +func (n *NotificationHandler) OnRawNotification(msg, detailsJSON string) { + notifyType := n.notificationType(msg) + switch { + case strings.HasPrefix(msg, "Resource.Loading"): + var detail ResourceLoadingDetail + _ = formJSON([]byte(msg), &detail) + n.OnResourceLoading(notifyType, detail) + return + case strings.HasPrefix(msg, "Controller.Action"): + var detail ControllerActionDetail + _ = formJSON([]byte(msg), &detail) + n.OnControllerAction(notifyType, detail) + return + case strings.HasPrefix(msg, "Tasker.Task"): + var detail TaskerTaskDetail + _ = formJSON([]byte(msg), &detail) + n.OnTaskerTask(notifyType, detail) + return + case strings.HasPrefix(msg, "Task.NextList"): + var detail TaskNextListDetail + _ = formJSON([]byte(msg), &detail) + n.OnTaskNextList(notifyType, detail) + return + case strings.HasPrefix(msg, "Task.Recognition"): + var detail TaskRecognitionDetail + _ = formJSON([]byte(msg), &detail) + n.OnTaskRecognition(notifyType, detail) + return + case strings.HasPrefix(msg, "Task.Action"): + var detail TaskActionDetail + _ = formJSON([]byte(msg), &detail) + n.OnTaskAction(notifyType, detail) + return + default: + n.OnUnknownNotification(msg, detailsJSON) + } +} + +func (n *NotificationHandler) OnUnknownNotification(_, _ string) { + // DO NOTHING +} + +func (n *NotificationHandler) notificationType(msg string) NotificationType { + switch { + case strings.HasSuffix(msg, ".Starting"): + return NotificationTypeStarting + case strings.HasSuffix(msg, "Succeeded"): + return NotificationTypeSucceeded + case strings.HasSuffix(msg, "Failed"): + return NotificationTypeFailed + default: + return NotificationTypeUnknown + } +} + +//export _MaaNotificationCallbackAgent +func _MaaNotificationCallbackAgent(msg, detailsJson C.StringView, notifyArg unsafe.Pointer) { + // Here, we are simply passing the uint64 value as a pointer + // and will not actually dereference this pointer. + id := uint64(uintptr(notifyArg)) + notify := notificationCallbackAgents[id] + if notify == nil { + return + } + notify.OnRawNotification(C.GoString(msg), C.GoString(detailsJson)) +} diff --git a/resource.go b/resource.go index 6cb4970..c75b358 100644 --- a/resource.go +++ b/resource.go @@ -31,7 +31,6 @@ extern uint8_t _MaaCustomActionCallbackAgent( import "C" import ( "github.com/MaaXYZ/maa-framework-go/internal/buffer" - "github.com/MaaXYZ/maa-framework-go/internal/notification" "github.com/MaaXYZ/maa-framework-go/internal/store" "unsafe" ) @@ -49,8 +48,8 @@ type Resource struct { } // NewResource creates a new resource. -func NewResource(callback func(msg, detailsJson string)) *Resource { - id := notification.RegisterCallback(callback) +func NewResource(notify Notification) *Resource { + id := registerNotificationCallback(notify) handle := C.MaaResourceCreate( C.MaaNotificationCallback(C._MaaNotificationCallbackAgent), // Here, we are simply passing the uint64 value as a pointer @@ -73,7 +72,7 @@ func NewResource(callback func(msg, detailsJson string)) *Resource { // Destroy frees the resource. func (r *Resource) Destroy() { value := resourceStore.Get(r.Handle()) - notification.UnregisterCallback(value.NotificationCallbackID) + unregisterNotificationCallback(value.NotificationCallbackID) resourceStore.Del(r.Handle()) C.MaaResourceDestroy(r.handle) } diff --git a/tasker.go b/tasker.go index 9c28a76..7379d87 100644 --- a/tasker.go +++ b/tasker.go @@ -9,7 +9,6 @@ extern void _MaaNotificationCallbackAgent(const char* message, const char* detai import "C" import ( "github.com/MaaXYZ/maa-framework-go/internal/buffer" - "github.com/MaaXYZ/maa-framework-go/internal/notification" "github.com/MaaXYZ/maa-framework-go/internal/store" "image" "time" @@ -23,8 +22,8 @@ type Tasker struct { } // NewTasker creates an new tasker. -func NewTasker(callback func(msg, detailsJson string)) *Tasker { - id := notification.RegisterCallback(callback) +func NewTasker(notify Notification) *Tasker { + id := registerNotificationCallback(notify) handle := C.MaaTaskerCreate( C.MaaNotificationCallback(C._MaaNotificationCallbackAgent), // Here, we are simply passing the uint64 value as a pointer @@ -41,7 +40,7 @@ func NewTasker(callback func(msg, detailsJson string)) *Tasker { // Destroy free the tasker. func (t *Tasker) Destroy() { id := taskerStore.Get(t.Handle()) - notification.UnregisterCallback(id) + unregisterNotificationCallback(id) taskerStore.Del(t.Handle()) C.MaaTaskerDestroy(t.handle) } diff --git a/toolkit.go b/toolkit.go index afc6dc9..2867cc7 100644 --- a/toolkit.go +++ b/toolkit.go @@ -30,7 +30,6 @@ extern void _MaaNotificationCallbackAgent(const char* message, const char* detai */ import "C" import ( - "github.com/MaaXYZ/maa-framework-go/internal/notification" "unsafe" ) @@ -198,7 +197,7 @@ func (t *Toolkit) ClearPICustom(instId uint64) { } // RunCli runs the PI CLI. -func (t *Toolkit) RunCli(instId uint64, resourcePath, userPath string, directly bool, callback func(msg, detailsJson string)) bool { +func (t *Toolkit) RunCli(instId uint64, resourcePath, userPath string, directly bool, notify Notification) bool { cResourcePath := C.CString(resourcePath) defer C.free(unsafe.Pointer(cResourcePath)) cUserPath := C.CString(userPath) @@ -207,7 +206,7 @@ func (t *Toolkit) RunCli(instId uint64, resourcePath, userPath string, directly if directly { cDirectly = 1 } - id := notification.RegisterCallback(callback) + id := registerNotificationCallback(notify) got := C.MaaToolkitProjectInterfaceRunCli( C.uint64_t(instId), cResourcePath, From 0cb25e95b0892a5d504d242c60d70f36a60300bd Mon Sep 17 00:00:00 2001 From: dongwlin Date: Fri, 20 Sep 2024 10:10:12 +0800 Subject: [PATCH 05/35] refactor: remove `Times` from `NodeDetail` --- tasker.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tasker.go b/tasker.go index 7379d87..f953ad1 100644 --- a/tasker.go +++ b/tasker.go @@ -199,7 +199,6 @@ type NodeDetail struct { ID int64 Name string Recognition *RecognitionDetail - Times uint64 RunCompleted bool } @@ -208,14 +207,12 @@ func (t *Tasker) getNodeDetail(nodeId int64) *NodeDetail { name := buffer.NewStringBuffer() defer name.Destroy() var recId int64 - var times uint64 var runCompleted uint8 got := C.MaaTaskerGetNodeDetail( t.handle, C.int64_t(nodeId), (*C.MaaStringBuffer)(name.Handle()), (*C.int64_t)(unsafe.Pointer(&recId)), - (*C.uint64_t)(unsafe.Pointer(×)), (*C.uint8_t)(unsafe.Pointer(&runCompleted)), ) if got == 0 { @@ -231,7 +228,6 @@ func (t *Tasker) getNodeDetail(nodeId int64) *NodeDetail { ID: nodeId, Name: name.Get(), Recognition: recognitionDetail, - Times: times, RunCompleted: runCompleted != 0, } } From 6f86b2b90925ab9720066ec7aa8e7ee791c579dc Mon Sep 17 00:00:00 2001 From: dongwlin Date: Fri, 20 Sep 2024 11:33:58 +0800 Subject: [PATCH 06/35] test: add NotificationHandler OnRawNotification test --- context_test.go | 48 ++++++++++++++++++++++---------------------- controller_test.go | 2 +- notification_test.go | 38 +++++++++++++++++++++++++++++++++++ resource_test.go | 4 ++-- tasker_test.go | 4 ++-- 5 files changed, 67 insertions(+), 29 deletions(-) create mode 100644 notification_test.go diff --git a/context_test.go b/context_test.go index aa97f94..2664b85 100644 --- a/context_test.go +++ b/context_test.go @@ -21,15 +21,15 @@ func (t *testContextRunPipelineAct) Run(ctx *Context, _ *CustomActionArg) bool { } func TestContext_RunPipeline(t *testing.T) { - ctrl := createDbgController(t) + ctrl := createDbgController(t, nil) defer ctrl.Destroy() isConnected := ctrl.PostConnect().Wait().Success() require.True(t, isConnected) - res := createResource(t) + res := createResource(t, nil) defer res.Destroy() - tasker := createTasker(t) + tasker := createTasker(t, nil) defer tasker.Destroy() taskerBind(t, tasker, ctrl, res) @@ -63,15 +63,15 @@ func (t *testContextRunRecognitionAct) Run(ctx *Context, _ *CustomActionArg) boo } func TestContext_RunRecognition(t *testing.T) { - ctrl := createDbgController(t) + ctrl := createDbgController(t, nil) defer ctrl.Destroy() isConnected := ctrl.PostConnect().Wait().Success() require.True(t, isConnected) - res := createResource(t) + res := createResource(t, nil) defer res.Destroy() - tasker := createTasker(t) + tasker := createTasker(t, nil) defer tasker.Destroy() taskerBind(t, tasker, ctrl, res) @@ -103,15 +103,15 @@ func (a testContextRunActionAct) Run(ctx *Context, arg *CustomActionArg) bool { } func TestContext_RunAction(t *testing.T) { - ctrl := createDbgController(t) + ctrl := createDbgController(t, nil) defer ctrl.Destroy() isConnected := ctrl.PostConnect().Wait().Success() require.True(t, isConnected) - res := createResource(t) + res := createResource(t, nil) defer res.Destroy() - tasker := createTasker(t) + tasker := createTasker(t, nil) defer tasker.Destroy() taskerBind(t, tasker, ctrl, res) @@ -153,15 +153,15 @@ func (t *testContextOverriderPipelineAct) Run(ctx *Context, _ *CustomActionArg) } func TestContext_OverridePipeline(t *testing.T) { - ctrl := createDbgController(t) + ctrl := createDbgController(t, nil) defer ctrl.Destroy() isConnected := ctrl.PostConnect().Wait().Success() require.True(t, isConnected) - res := createResource(t) + res := createResource(t, nil) defer res.Destroy() - tasker := createTasker(t) + tasker := createTasker(t, nil) defer tasker.Destroy() taskerBind(t, tasker, ctrl, res) @@ -200,15 +200,15 @@ func (t *testContextOverrideNextAct) Run(ctx *Context, _ *CustomActionArg) bool } func TestContext_OverrideNext(t *testing.T) { - ctrl := createDbgController(t) + ctrl := createDbgController(t, nil) defer ctrl.Destroy() isConnected := ctrl.PostConnect().Wait().Success() require.True(t, isConnected) - res := createResource(t) + res := createResource(t, nil) defer res.Destroy() - tasker := createTasker(t) + tasker := createTasker(t, nil) defer tasker.Destroy() taskerBind(t, tasker, ctrl, res) @@ -235,15 +235,15 @@ func (t *testContextGetTaskJobAct) Run(ctx *Context, _ *CustomActionArg) bool { } func TestContext_GetTaskJob(t *testing.T) { - ctrl := createDbgController(t) + ctrl := createDbgController(t, nil) defer ctrl.Destroy() isConnected := ctrl.PostConnect().Wait().Success() require.True(t, isConnected) - res := createResource(t) + res := createResource(t, nil) defer res.Destroy() - tasker := createTasker(t) + tasker := createTasker(t, nil) defer tasker.Destroy() taskerBind(t, tasker, ctrl, res) @@ -270,15 +270,15 @@ func (t testContextGetTaskerAct) Run(ctx *Context, _ *CustomActionArg) bool { } func TestContext_GetTasker(t *testing.T) { - ctrl := createDbgController(t) + ctrl := createDbgController(t, nil) defer ctrl.Destroy() isConnected := ctrl.PostConnect().Wait().Success() require.True(t, isConnected) - res := createResource(t) + res := createResource(t, nil) defer res.Destroy() - tasker := createTasker(t) + tasker := createTasker(t, nil) defer tasker.Destroy() taskerBind(t, tasker, ctrl, res) @@ -303,15 +303,15 @@ func (t testContextCloneAct) Run(ctx *Context, _ *CustomActionArg) bool { } func TestContext_Clone(t *testing.T) { - ctrl := createDbgController(t) + ctrl := createDbgController(t, nil) defer ctrl.Destroy() isConnected := ctrl.PostConnect().Wait().Success() require.True(t, isConnected) - res := createResource(t) + res := createResource(t, nil) defer res.Destroy() - tasker := createTasker(t) + tasker := createTasker(t, nil) defer tasker.Destroy() taskerBind(t, tasker, ctrl, res) diff --git a/controller_test.go b/controller_test.go index 49de9db..ff2d099 100644 --- a/controller_test.go +++ b/controller_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func createDbgController(t *testing.T) Controller { +func createDbgController(t *testing.T, notify Notification) Controller { testingPath := "./test/data_set/PipelineSmoking/Screenshot" resultPath := "./test/data_set/debug" diff --git a/notification_test.go b/notification_test.go new file mode 100644 index 0000000..49b2afc --- /dev/null +++ b/notification_test.go @@ -0,0 +1,38 @@ +package maa + +import ( + "fmt" + "github.com/stretchr/testify/require" + "testing" +) + +type testNotificationHandlerOnRawNotification struct { + *NotificationHandler +} + +func (t *testNotificationHandlerOnRawNotification) OnRawNotification(msg, detailsJson string) { + fmt.Printf("TestNotificationHandler_OnRawNotification, msg: %s, detailsJson: %s\n", msg, detailsJson) + t.NotificationHandler.OnRawNotification(msg, detailsJson) +} + +func TestNotificationHandler_OnRawNotification(t *testing.T) { + ctrl := createDbgController(t, &testNotificationHandlerOnRawNotification{}) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + + res := createResource(t, &testNotificationHandlerOnRawNotification{}) + defer res.Destroy() + + tasker := createTasker(t, &testNotificationHandlerOnRawNotification{}) + defer tasker.Destroy() + taskerBind(t, tasker, ctrl, res) + + got := tasker.PostPipeline("TestNotificationHandler_OnRawNotification", J{ + "TestNotificationHandler_OnRawNotification": J{ + "action": "Click", + "target": []int{100, 200, 100, 100}, + }, + }).Wait().Success() + require.True(t, got) +} diff --git a/resource_test.go b/resource_test.go index 1d71570..0f92ef0 100644 --- a/resource_test.go +++ b/resource_test.go @@ -5,8 +5,8 @@ import ( "testing" ) -func createResource(t *testing.T) *Resource { - res := NewResource(nil) +func createResource(t *testing.T, notify Notification) *Resource { + res := NewResource(notify) require.NotNil(t, res) return res } diff --git a/tasker_test.go b/tasker_test.go index f57a868..edcd4a8 100644 --- a/tasker_test.go +++ b/tasker_test.go @@ -5,8 +5,8 @@ import ( "testing" ) -func createTasker(t *testing.T) *Tasker { - tasker := NewTasker(nil) +func createTasker(t *testing.T, notify Notification) *Tasker { + tasker := NewTasker(notify) require.NotNil(t, tasker) return tasker } From 9b7349f55b4e4d2cf11fea4ef1e3aa52bf83954c Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sat, 21 Sep 2024 22:17:47 +0800 Subject: [PATCH 07/35] test: add resource test --- resource_test.go | 300 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) diff --git a/resource_test.go b/resource_test.go index 0f92ef0..56b1558 100644 --- a/resource_test.go +++ b/resource_test.go @@ -10,3 +10,303 @@ func createResource(t *testing.T, notify Notification) *Resource { require.NotNil(t, res) return res } + +func TestNewResource(t *testing.T) { + res := createResource(t, nil) + res.Destroy() +} + +func TestResource_Handle(t *testing.T) { + res := createResource(t, nil) + defer res.Destroy() + handle := res.Handle() + require.NotNil(t, handle) +} + +type testResourceTestRec struct{} + +func (t *testResourceTestRec) Run(_ *Context, _ *CustomRecognitionArg) (CustomRecognitionResult, bool) { + return CustomRecognitionResult{}, true +} + +func TestResource_RegisterCustomRecognition(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + + res := createResource(t, nil) + defer res.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + taskerBind(t, tasker, ctrl, res) + + got1 := res.RegisterCustomRecognition("TestRec", &testResourceTestRec{}) + require.True(t, got1) + + got2 := tasker.PostPipeline("TestResource_RegisterCustomRecognition", J{ + "TestResource_RegisterCustomRecognition": J{ + "recognition": "custom", + "custom_recognition": "TestRec", + }, + }).Wait().Success() + require.True(t, got2) +} + +func TestResource_UnregisterCustomRecognition(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + + res := createResource(t, nil) + defer res.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + taskerBind(t, tasker, ctrl, res) + + got1 := res.RegisterCustomRecognition("TestRec", &testResourceTestRec{}) + require.True(t, got1) + + got2 := tasker.PostPipeline("TestResource_UnregisterCustomRecognition", J{ + "TestResource_UnregisterCustomRecognition": J{ + "recognition": "custom", + "custom_recognition": "TestRec", + }, + }).Wait().Success() + require.True(t, got2) + + got3 := res.UnregisterCustomRecognition("TestRec") + require.True(t, got3) + + got4 := tasker.PostPipeline("TestResource_UnregisterCustomRecognition", J{ + "TestResource_UnregisterCustomRecognition": J{ + "recognition": "custom", + "custom_recognition": "TestRec", + }, + }).Wait().Failure() + require.True(t, got4) +} + +func TestResource_ClearCustomRecognition(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + + res := createResource(t, nil) + defer res.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + taskerBind(t, tasker, ctrl, res) + + got1 := res.RegisterCustomRecognition("TestRec1", &testResourceTestRec{}) + require.True(t, got1) + got2 := res.RegisterCustomRecognition("TestRec2", &testResourceTestRec{}) + require.True(t, got2) + + got3 := tasker.PostPipeline("TestResource_ClearCustomRecognition", J{ + "TestResource_ClearCustomRecognition": J{ + "recognition": "custom", + "custom_recognition": "TestRec1", + }, + }).Wait().Success() + require.True(t, got3) + got4 := tasker.PostPipeline("TestResource_ClearCustomRecognition", J{ + "TestResource_ClearCustomRecognition": J{ + "recognition": "custom", + "custom_recognition": "TestRec2", + }, + }).Wait().Success() + require.True(t, got4) + + got5 := res.ClearCustomRecognition() + require.True(t, got5) + + got6 := tasker.PostPipeline("TestResource_ClearCustomRecognition", J{ + "TestResource_ClearCustomRecognition": J{ + "recognition": "custom", + "custom_recognition": "TestRec1", + }, + }).Wait().Failure() + require.True(t, got6) + got7 := tasker.PostPipeline("TestResource_ClearCustomRecognition", J{ + "TestResource_ClearCustomRecognition": J{ + "recognition": "custom", + "custom_recognition": "TestRec2", + }, + }).Wait().Failure() + require.True(t, got7) +} + +type testResourceTestAct struct{} + +func (t *testResourceTestAct) Run(_ *Context, _ *CustomActionArg) bool { + return true +} + +func TestResource_RegisterCustomAction(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + + res := createResource(t, nil) + defer res.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + taskerBind(t, tasker, ctrl, res) + + registered := res.RegisterCustomAction("TestAct", &testResourceTestAct{}) + require.True(t, registered) + + got := tasker.PostPipeline("TestResource_RegisterCustomAction", J{ + "TestResource_RegisterCustomAction": J{ + "action": "custom", + "custom_action": "TestAct", + }, + }).Wait().Success() + require.True(t, got) +} + +func TestResource_UnregisterCustomAction(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + + res := createResource(t, nil) + defer res.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + taskerBind(t, tasker, ctrl, res) + + registered := res.RegisterCustomAction("TestAct", &testResourceTestAct{}) + require.True(t, registered) + + got1 := tasker.PostPipeline("TestResource_RegisterCustomAction", J{ + "TestResource_RegisterCustomAction": J{ + "action": "custom", + "custom_action": "TestAct", + }, + }).Wait().Success() + require.True(t, got1) + + unregistered := res.UnregisterCustomAction("TestAct") + require.True(t, unregistered) + + got2 := tasker.PostPipeline("TestResource_RegisterCustomAction", J{ + "TestResource_RegisterCustomAction": J{ + "action": "custom", + "custom_action": "TestAct", + }, + }).Wait().Failure() + require.True(t, got2) +} + +func TestResource_ClearCustomAction(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + + res := createResource(t, nil) + defer res.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + taskerBind(t, tasker, ctrl, res) + + registered1 := res.RegisterCustomAction("TestAct1", &testResourceTestAct{}) + require.True(t, registered1) + registered2 := res.RegisterCustomAction("TestAct2", &testResourceTestAct{}) + require.True(t, registered2) + + got1 := tasker.PostPipeline("TestResource_RegisterCustomAction", J{ + "TestResource_RegisterCustomAction": J{ + "action": "custom", + "custom_action": "TestAct1", + }, + }).Wait().Success() + require.True(t, got1) + got2 := tasker.PostPipeline("TestResource_RegisterCustomAction", J{ + "TestResource_RegisterCustomAction": J{ + "action": "custom", + "custom_action": "TestAct2", + }, + }).Wait().Success() + require.True(t, got2) + + cleared := res.ClearCustomAction() + require.True(t, cleared) + + got3 := tasker.PostPipeline("TestResource_RegisterCustomAction", J{ + "TestResource_RegisterCustomAction": J{ + "action": "custom", + "custom_action": "TestAct1", + }, + }).Wait().Failure() + require.True(t, got3) + got4 := tasker.PostPipeline("TestResource_RegisterCustomAction", J{ + "TestResource_RegisterCustomAction": J{ + "action": "custom", + "custom_action": "TestAct2", + }, + }).Wait().Failure() + require.True(t, got4) +} + +func TestResource_PostPath(t *testing.T) { + res := createResource(t, nil) + defer res.Destroy() + resDir := "./test/data_set/PipelineSmoking/resource" + isPathSet := res.PostPath(resDir).Wait().Success() + require.True(t, isPathSet) +} + +func TestResource_Clear(t *testing.T) { + res := createResource(t, nil) + defer res.Destroy() + resDir := "./test/data_set/PipelineSmoking/resource" + isPathSet := res.PostPath(resDir).Wait().Success() + require.True(t, isPathSet) + cleared := res.Clear() + require.True(t, cleared) +} + +func TestResource_Loaded(t *testing.T) { + res := createResource(t, nil) + defer res.Destroy() + resDir := "./test/data_set/PipelineSmoking/resource" + isPathSet := res.PostPath(resDir).Wait().Success() + require.True(t, isPathSet) + loaded := res.Loaded() + require.True(t, loaded) +} + +func TestResource_GetHash(t *testing.T) { + res := createResource(t, nil) + defer res.Destroy() + resDir := "./test/data_set/PipelineSmoking/resource" + isPathSet := res.PostPath(resDir).Wait().Success() + require.True(t, isPathSet) + hash, ok := res.GetHash() + require.True(t, ok) + require.NotEmpty(t, hash) +} + +func TestResource_GetTaskList(t *testing.T) { + res := createResource(t, nil) + defer res.Destroy() + resDir := "./test/data_set/PipelineSmoking/resource" + isPathSet := res.PostPath(resDir).Wait().Success() + require.True(t, isPathSet) + taskList, ok := res.GetTaskList() + require.True(t, ok) + require.NotEmpty(t, taskList) +} From 9bfc36c984a77f55cd56633dfdaccc59de414f1c Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sat, 21 Sep 2024 23:46:57 +0800 Subject: [PATCH 08/35] test: refine `TestResource_GetHash` --- resource_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resource_test.go b/resource_test.go index 56b1558..1183220 100644 --- a/resource_test.go +++ b/resource_test.go @@ -297,7 +297,7 @@ func TestResource_GetHash(t *testing.T) { require.True(t, isPathSet) hash, ok := res.GetHash() require.True(t, ok) - require.NotEmpty(t, hash) + require.NotEqual(t, "0", hash) } func TestResource_GetTaskList(t *testing.T) { From a73f0b3d983826994b8c06dc212509fa7eff580f Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 02:44:28 +0800 Subject: [PATCH 09/35] test: add controller test --- controller_test.go | 166 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/controller_test.go b/controller_test.go index ff2d099..23215e9 100644 --- a/controller_test.go +++ b/controller_test.go @@ -13,3 +13,169 @@ func createDbgController(t *testing.T, notify Notification) Controller { require.NotNil(t, ctrl) return ctrl } + +func TestNewDbgController(t *testing.T) { + ctrl := createDbgController(t, nil) + ctrl.Destroy() +} + +func TestController_Handle(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + handle := ctrl.Handle() + require.NotNil(t, handle) +} + +func TestController_SetScreenshotTargetLongSide(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + got := ctrl.SetScreenshotTargetLongSide(1280) + require.True(t, got) +} + +func TestController_SetScreenshotTargetShortSide(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + got := ctrl.SetScreenshotTargetShortSide(720) + require.True(t, got) +} + +func TestController_SetRecording(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + got := ctrl.SetRecording(true) + require.True(t, got) +} + +func TestController_PostConnect(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) +} + +func TestController_Connected(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + connected := ctrl.Connected() + require.True(t, connected) +} + +func TestController_PostClick(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + clicked := ctrl.PostClick(100, 200).Wait().Success() + require.True(t, clicked) +} + +func TestController_PostSwipe(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + swiped := ctrl.PostSwipe(100, 200, 400, 300, 2000).Wait().Success() + require.True(t, swiped) +} + +func TestController_PostPressKey(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + pressed := ctrl.PostPressKey(4).Wait().Success() + require.True(t, pressed) +} + +func TestController_PostInputText(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + inputted := ctrl.PostInputText("Hello World").Wait().Success() + require.True(t, inputted) +} + +func TestController_PostStartApp(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + started := ctrl.PostStartApp("com.android.settings").Wait().Success() + require.True(t, started) +} + +func TestController_PostStopApp(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + stopped := ctrl.PostStopApp("com.android.settings").Wait().Success() + require.True(t, stopped) +} + +func TestController_PostTouchDown(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + downed := ctrl.PostTouchDown(0, 100, 200, 1000).Wait().Success() + require.True(t, downed) +} + +func TestController_PostTouchMove(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + downed := ctrl.PostTouchDown(0, 100, 200, 1000).Wait().Success() + require.True(t, downed) + moved := ctrl.PostTouchMove(0, 200, 300, 1000).Wait().Success() + require.True(t, moved) +} + +func TestController_PostTouchUp(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + downed := ctrl.PostTouchDown(0, 100, 200, 1000).Wait().Success() + require.True(t, downed) + moved := ctrl.PostTouchMove(0, 200, 300, 1000).Wait().Success() + require.True(t, moved) + upped := ctrl.PostTouchUp(0).Wait().Success() + require.True(t, upped) +} + +func TestController_PostScreencap(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + screencaped := ctrl.PostScreencap().Wait().Success() + require.True(t, screencaped) +} + +func TestController_CacheImage(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + screencaped := ctrl.PostScreencap().Wait().Success() + require.True(t, screencaped) + img := ctrl.CacheImage() + require.NotNil(t, img) +} + +func TestController_GetUUID(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + uuid, oK := ctrl.GetUUID() + require.True(t, oK) + require.NotEmpty(t, uuid) +} From b634b55f09ac389dbe2d95e9dae5f9d1e48cf6e3 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 02:47:02 +0800 Subject: [PATCH 10/35] test: fix notify without use in createDbgController --- controller_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller_test.go b/controller_test.go index 23215e9..60fa06b 100644 --- a/controller_test.go +++ b/controller_test.go @@ -9,7 +9,7 @@ func createDbgController(t *testing.T, notify Notification) Controller { testingPath := "./test/data_set/PipelineSmoking/Screenshot" resultPath := "./test/data_set/debug" - ctrl := NewDbgController(testingPath, resultPath, DbgControllerTypeCarouselImage, "{}", nil) + ctrl := NewDbgController(testingPath, resultPath, DbgControllerTypeCarouselImage, "{}", notify) require.NotNil(t, ctrl) return ctrl } From bfd36e90f62f9a83cab66cc860a3e757425880e3 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 12:35:20 +0800 Subject: [PATCH 11/35] refactor: time.Duration as duration type --- controller.go | 14 +++++++++++--- controller_test.go | 3 ++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/controller.go b/controller.go index 8336eb4..dcce0e5 100644 --- a/controller.go +++ b/controller.go @@ -11,6 +11,7 @@ import ( "github.com/MaaXYZ/maa-framework-go/internal/buffer" "github.com/MaaXYZ/maa-framework-go/internal/store" "image" + "time" "unsafe" ) @@ -25,7 +26,7 @@ type Controller interface { PostConnect() *Job PostClick(x, y int32) *Job - PostSwipe(x1, y1, x2, y2, duration int32) *Job + PostSwipe(x1, y1, x2, y2 int32, duration time.Duration) *Job PostPressKey(keycode int32) *Job PostInputText(text string) *Job PostStartApp(intent string) *Job @@ -352,8 +353,15 @@ func (c *controller) PostClick(x, y int32) *Job { } // PostSwipe posts a swipe. -func (c *controller) PostSwipe(x1, y1, x2, y2, duration int32) *Job { - id := int64(C.MaaControllerPostSwipe(c.handle, C.int32_t(x1), C.int32_t(y1), C.int32_t(x2), C.int32_t(y2), C.int32_t(duration))) +func (c *controller) PostSwipe(x1, y1, x2, y2 int32, duration time.Duration) *Job { + id := int64(C.MaaControllerPostSwipe( + c.handle, + C.int32_t(x1), + C.int32_t(y1), + C.int32_t(x2), + C.int32_t(y2), + C.int32_t(duration.Milliseconds()), + )) return NewJob(id, c.status, c.wait) } diff --git a/controller_test.go b/controller_test.go index 60fa06b..44d05ca 100644 --- a/controller_test.go +++ b/controller_test.go @@ -3,6 +3,7 @@ package maa import ( "github.com/stretchr/testify/require" "testing" + "time" ) func createDbgController(t *testing.T, notify Notification) Controller { @@ -77,7 +78,7 @@ func TestController_PostSwipe(t *testing.T) { defer ctrl.Destroy() isConnected := ctrl.PostConnect().Wait().Success() require.True(t, isConnected) - swiped := ctrl.PostSwipe(100, 200, 400, 300, 2000).Wait().Success() + swiped := ctrl.PostSwipe(100, 200, 400, 300, 2*time.Second).Wait().Success() require.True(t, swiped) } From 3d7303e59aa176d30f83b1ca6855b6f68b8ef48f Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 13:12:35 +0800 Subject: [PATCH 12/35] refactor: rename Initialized --- tasker.go | 4 ++-- test/pipleline_smoking_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tasker.go b/tasker.go index f953ad1..5f04c19 100644 --- a/tasker.go +++ b/tasker.go @@ -60,8 +60,8 @@ func (t *Tasker) BindController(ctrl Controller) bool { return C.MaaTaskerBindController(t.handle, (*C.MaaController)(ctrl.Handle())) != 0 } -// Inited checks if the tasker is initialized. -func (t *Tasker) Inited() bool { +// Initialized checks if the tasker is initialized. +func (t *Tasker) Initialized() bool { return C.MaaTaskerInited(t.handle) != 0 } diff --git a/test/pipleline_smoking_test.go b/test/pipleline_smoking_test.go index 2770cb0..5b13736 100644 --- a/test/pipleline_smoking_test.go +++ b/test/pipleline_smoking_test.go @@ -31,7 +31,7 @@ func TestPipelineSmoking(t *testing.T) { isCtrlBound := tasker.BindController(ctrl) require.True(t, isCtrlBound) - isInitialized := tasker.Inited() + isInitialized := tasker.Initialized() require.True(t, isInitialized) got := tasker.PostPipeline("Wilderness").Wait().Success() From fc67006a23663cff2f58a3b7a6f6edf0ae77f30a Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 13:48:34 +0800 Subject: [PATCH 13/35] refactor: remove WaitAll function of Tasker --- tasker.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tasker.go b/tasker.go index 5f04c19..c2967de 100644 --- a/tasker.go +++ b/tasker.go @@ -11,7 +11,6 @@ import ( "github.com/MaaXYZ/maa-framework-go/internal/buffer" "github.com/MaaXYZ/maa-framework-go/internal/store" "image" - "time" "unsafe" ) @@ -107,13 +106,6 @@ func (t *Tasker) wait(id int64) Status { return Status(C.MaaTaskerWait(t.handle, C.int64_t(id))) } -// WaitAll waits for all tasks to complete. -func (t *Tasker) WaitAll() { - for t.Running() { - time.Sleep(time.Millisecond * 10) - } -} - // Running checks if the instance running. func (t *Tasker) Running() bool { return C.MaaTaskerRunning(t.handle) != 0 From 4b32b75fc5a9f69619fa6486a708f9bcaea553ec Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 13:49:11 +0800 Subject: [PATCH 14/35] test: add tasker test --- tasker_test.go | 175 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) diff --git a/tasker_test.go b/tasker_test.go index edcd4a8..b2919af 100644 --- a/tasker_test.go +++ b/tasker_test.go @@ -3,6 +3,7 @@ package maa import ( "github.com/stretchr/testify/require" "testing" + "time" ) func createTasker(t *testing.T, notify Notification) *Tasker { @@ -17,3 +18,177 @@ func taskerBind(t *testing.T, tasker *Tasker, ctrl Controller, res *Resource) { isCtrlBound := tasker.BindController(ctrl) require.True(t, isCtrlBound) } + +func TestNewTasker(t *testing.T) { + tasker := createTasker(t, nil) + tasker.Destroy() +} + +func TestTasker_Handle(t *testing.T) { + tasker := createTasker(t, nil) + defer tasker.Destroy() + handle := tasker.Handle() + require.NotNil(t, handle) +} + +func TestTasker_BindResource(t *testing.T) { + res := createResource(t, nil) + defer res.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + bound := tasker.BindResource(res) + require.True(t, bound) +} + +func TestTasker_BindController(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + bound := tasker.BindController(ctrl) + require.True(t, bound) +} + +func TestTasker_Initialized(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + connected := ctrl.PostConnect().Wait().Success() + require.True(t, connected) + + res := createResource(t, nil) + defer res.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + taskerBind(t, tasker, ctrl, res) + + initialized := tasker.Initialized() + require.True(t, initialized) +} + +func TestTasker_PostPipeline(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + + res := createResource(t, nil) + defer res.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + taskerBind(t, tasker, ctrl, res) + + got := tasker.PostPipeline("TestTasker_PostPipeline", J{ + "TestTasker_PostPipeline": J{ + "action": "Click", + "target": []int{100, 200, 100, 100}, + }, + }).Wait().Success() + require.True(t, got) +} + +func TestTasker_Running(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + + res := createResource(t, nil) + defer res.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + taskerBind(t, tasker, ctrl, res) + + got := tasker.Running() + require.False(t, got) +} + +func TestTasker_PostStop(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + + res := createResource(t, nil) + defer res.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + taskerBind(t, tasker, ctrl, res) + + got := tasker.PostStop() + require.True(t, got) +} + +func TestTasker_GetResource(t *testing.T) { + res1 := createResource(t, nil) + defer res1.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + bound := tasker.BindResource(res1) + require.True(t, bound) + + res2 := tasker.GetResource() + require.NotNil(t, res2) + require.Equal(t, res1.Handle(), res2.Handle()) +} + +func TestTasker_GetController(t *testing.T) { + ctrl1 := createDbgController(t, nil) + defer ctrl1.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + bound := tasker.BindController(ctrl1) + require.True(t, bound) + + ctrl2 := tasker.GetController() + require.NotNil(t, ctrl2) + require.Equal(t, ctrl1.Handle(), ctrl2.Handle()) +} + +func TestTasker_ClearCache(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + + res := createResource(t, nil) + defer res.Destroy() + + tasker := createTasker(t, nil) + defer tasker.Destroy() + taskerBind(t, tasker, ctrl, res) + + got := tasker.ClearCache() + require.True(t, got) +} + +func TestTasker_GetLatestNode(t *testing.T) { + ctrl := createDbgController(t, nil) + defer ctrl.Destroy() + isConnected := ctrl.PostConnect().Wait().Success() + require.True(t, isConnected) + + res := createResource(t, nil) + defer res.Destroy() + resDir := "./test/data_set/PipelineSmoking/resource" + isPathSet := res.PostPath(resDir).Wait().Success() + require.True(t, isPathSet) + + tasker := createTasker(t, nil) + defer tasker.Destroy() + taskerBind(t, tasker, ctrl, res) + job := tasker.PostPipeline("Wilderness") + require.NotNil(t, job) + time.Sleep(2 * time.Second) + detail := tasker.GetLatestNode("Wilderness") + t.Log(detail) + got := job.Wait().Success() + require.True(t, got) +} From 9446ea135287ca11a18cc7f1ba23f588c1f1d566 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 13:57:43 +0800 Subject: [PATCH 15/35] docs: update examples --- README.md | 6 +++--- README_zh.md | 6 +++--- examples/custom-action/main.go | 2 +- examples/custom-recognition/main.go | 2 +- examples/quick-start/main.go | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 114127f..ef67182 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ func main() { defer res.Destroy() res.PostPath("./resource").Wait() tasker.BindResource(res) - if tasker.Inited() { + if tasker.Initialized() { fmt.Println("Failed to init MAA.") os.Exit(1) } @@ -190,7 +190,7 @@ func main() { defer res.Destroy() res.PostPath("./resource").Wait() tasker.BindResource(res) - if tasker.Inited() { + if tasker.Initialized() { fmt.Println("Failed to init MAA.") os.Exit(1) } @@ -276,7 +276,7 @@ func main() { defer res.Destroy() res.PostPath("./resource").Wait() tasker.BindResource(res) - if tasker.Inited() { + if tasker.Initialized() { fmt.Println("Failed to init MAA.") os.Exit(1) } diff --git a/README_zh.md b/README_zh.md index aba7253..34526d3 100644 --- a/README_zh.md +++ b/README_zh.md @@ -139,7 +139,7 @@ func main() { defer res.Destroy() res.PostPath("./resource").Wait() tasker.BindResource(res) - if tasker.Inited() { + if tasker.Initialized() { fmt.Println("Failed to init MAA.") os.Exit(1) } @@ -189,7 +189,7 @@ func main() { defer res.Destroy() res.PostPath("./resource").Wait() tasker.BindResource(res) - if tasker.Inited() { + if tasker.Initialized() { fmt.Println("Failed to init MAA.") os.Exit(1) } @@ -275,7 +275,7 @@ func main() { defer res.Destroy() res.PostPath("./resource").Wait() tasker.BindResource(res) - if tasker.Inited() { + if tasker.Initialized() { fmt.Println("Failed to init MAA.") os.Exit(1) } diff --git a/examples/custom-action/main.go b/examples/custom-action/main.go index 301eabb..bc112ba 100644 --- a/examples/custom-action/main.go +++ b/examples/custom-action/main.go @@ -30,7 +30,7 @@ func main() { defer res.Destroy() res.PostPath("./resource").Wait() tasker.BindResource(res) - if tasker.Inited() { + if tasker.Initialized() { fmt.Println("Failed to init MAA.") os.Exit(1) } diff --git a/examples/custom-recognition/main.go b/examples/custom-recognition/main.go index 1295b4f..637763a 100644 --- a/examples/custom-recognition/main.go +++ b/examples/custom-recognition/main.go @@ -30,7 +30,7 @@ func main() { defer res.Destroy() res.PostPath("./resource").Wait() tasker.BindResource(res) - if tasker.Inited() { + if tasker.Initialized() { fmt.Println("Failed to init MAA.") os.Exit(1) } diff --git a/examples/quick-start/main.go b/examples/quick-start/main.go index 11d751d..4296bff 100644 --- a/examples/quick-start/main.go +++ b/examples/quick-start/main.go @@ -30,7 +30,7 @@ func main() { defer res.Destroy() res.PostPath("./resource").Wait() tasker.BindResource(res) - if tasker.Inited() { + if tasker.Initialized() { fmt.Println("Failed to init MAA.") os.Exit(1) } From 680dcd85d84cec2fa3ed8f2a3b7906b3ec7222b1 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 14:10:30 +0800 Subject: [PATCH 16/35] test: add toolkit test --- toolkit_test.go | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 toolkit_test.go diff --git a/toolkit_test.go b/toolkit_test.go new file mode 100644 index 0000000..6158936 --- /dev/null +++ b/toolkit_test.go @@ -0,0 +1,63 @@ +package maa + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func createToolkit(t *testing.T) *Toolkit { + toolkit := NewToolkit() + require.NotNil(t, toolkit) + return toolkit +} + +func TestNewToolkit(t *testing.T) { + createToolkit(t) +} + +func TestToolkit_ConfigInitOption(t *testing.T) { + toolkit := createToolkit(t) + got := toolkit.ConfigInitOption("./test", "{}") + require.True(t, got) +} + +func TestToolkit_FindAdbDevices(t *testing.T) { + toolkit := createToolkit(t) + adbDevices := toolkit.FindAdbDevices() + require.NotNil(t, adbDevices) +} + +func TestToolkit_FindDesktopWindows(t *testing.T) { + toolkit := createToolkit(t) + desktopWindows := toolkit.FindDesktopWindows() + require.NotNil(t, desktopWindows) +} + +type testToolKitRec struct{} + +func (t *testToolKitRec) Run(_ *Context, _ *CustomRecognitionArg) (CustomRecognitionResult, bool) { + return CustomRecognitionResult{}, true +} + +func TestToolkit_RegisterPICustomRecognition(t *testing.T) { + toolkit := createToolkit(t) + toolkit.RegisterPICustomRecognition(0, "TestRec", &testToolKitRec{}) +} + +type testToolkitAct struct{} + +func (t testToolkitAct) Run(_ *Context, _ *CustomActionArg) bool { + return true +} + +func TestToolkit_RegisterPICustomAction(t *testing.T) { + toolkit := createToolkit(t) + toolkit.RegisterPICustomAction(0, "TestAct", &testToolkitAct{}) +} + +func TestToolkit_ClearPICustom(t *testing.T) { + toolkit := createToolkit(t) + toolkit.RegisterPICustomRecognition(0, "TestRec", &testToolKitRec{}) + toolkit.RegisterPICustomAction(0, "TestAct", &testToolkitAct{}) + toolkit.ClearPICustom(0) +} From db88b0a7ef95aa0511eb21d162596e81334ad342 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 14:11:31 +0800 Subject: [PATCH 17/35] chore: ignore /test/config --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e4d45a8..665b08e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /.idea -/test/debug \ No newline at end of file +/test/debug +/test/config \ No newline at end of file From c573cfef8fbd228c3fc37a7a3ecedda197306f9e Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 18:00:27 +0800 Subject: [PATCH 18/35] refactor: remove unused --- internal/buffer/image_buffer.go | 67 ++------------------------------- 1 file changed, 3 insertions(+), 64 deletions(-) diff --git a/internal/buffer/image_buffer.go b/internal/buffer/image_buffer.go index fd382f2..78482c7 100644 --- a/internal/buffer/image_buffer.go +++ b/internal/buffer/image_buffer.go @@ -6,12 +6,9 @@ package buffer */ import "C" import ( - "bytes" - "errors" "image" "image/color" "image/draw" - "image/png" "unsafe" ) @@ -21,6 +18,9 @@ type ImageBuffer struct { func NewImageBuffer() *ImageBuffer { handle := C.MaaImageBufferCreate() + if handle == nil { + return nil + } return &ImageBuffer{ handle: handle, } @@ -139,64 +139,3 @@ func (i *ImageBuffer) setRawData(data unsafe.Pointer, width, height, imageType i C.int32_t(imageType), ) != 0 } - -// GetByEncoded retrieves the decoded image from the buffer. -// It returns the decoded image and an error if the operation was unsuccessful. -func (i *ImageBuffer) GetByEncoded() (image.Image, error) { - encodedData := i.getEncoded() - if encodedData == nil { - return nil, errors.New("failed to get encoded image data") - } - dataSize := i.getEncodedSize() - if dataSize == 0 { - return nil, errors.New("encoded image size is zero") - } - - data := C.GoBytes(encodedData, C.int32_t(dataSize)) - img, err := png.Decode(bytes.NewReader(data)) - if err != nil { - return nil, err - } - return img, nil -} - -// SetEncoded encodes the given image and sets it in the buffer. -// It takes an image.Image as input and returns an error if the operation was unsuccessful. -func (i *ImageBuffer) SetEncoded(img image.Image) error { - var buf bytes.Buffer - if err := png.Encode(&buf, img); err != nil { - return err - } - - data := buf.Bytes() - cData := C.CBytes(data) - defer C.free(cData) - - if !i.setEncoded(cData, uint64(len(data))) { - return errors.New("failed to set encoded image data") - } - return nil -} - -// getEncoded retrieves the encoded image data from the buffer. -// It returns a pointer to the encoded image data. -func (i *ImageBuffer) getEncoded() unsafe.Pointer { - return unsafe.Pointer(C.MaaImageBufferGetEncoded(i.handle)) -} - -// getEncodedSize retrieves the size of the encoded image data in the buffer. -// It returns the size of the encoded image data as an integer. -func (i *ImageBuffer) getEncodedSize() int32 { - return int32(C.MaaImageBufferGetEncodedSize(i.handle)) -} - -// setEncoded sets the encoded image data in the buffer. -// It takes a pointer to the encoded image data and the size of the data. -// It returns true if the operation was successful, otherwise false. -func (i *ImageBuffer) setEncoded(data unsafe.Pointer, size uint64) bool { - return C.MaaImageBufferSetEncoded( - i.handle, - C.MaaImageEncodedData(data), - C.uint64_t(size), - ) != 0 -} From 4d7a57471bc2b65e91d353f5e050752b24ed200f Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 18:00:45 +0800 Subject: [PATCH 19/35] test: add image buffer test --- internal/buffer/image_buffer_test.go | 59 ++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 internal/buffer/image_buffer_test.go diff --git a/internal/buffer/image_buffer_test.go b/internal/buffer/image_buffer_test.go new file mode 100644 index 0000000..5763c19 --- /dev/null +++ b/internal/buffer/image_buffer_test.go @@ -0,0 +1,59 @@ +package buffer + +import ( + "github.com/stretchr/testify/require" + "image" + "image/color" + "testing" +) + +func createImageBuffer(t *testing.T) *ImageBuffer { + imageBuffer := NewImageBuffer() + require.NotNil(t, imageBuffer) + return imageBuffer +} + +func TestNewImageBuffer(t *testing.T) { + imageBuffer := createImageBuffer(t) + imageBuffer.Destroy() +} + +func TestImageBuffer_Handle(t *testing.T) { + imageBuffer := createImageBuffer(t) + defer imageBuffer.Destroy() + handle := imageBuffer.Handle() + require.NotNil(t, handle) +} + +func TestImageBuffer_IsEmpty(t *testing.T) { + imageBuffer := createImageBuffer(t) + defer imageBuffer.Destroy() + got := imageBuffer.IsEmpty() + require.True(t, got) +} + +func TestImageBuffer_Clear(t *testing.T) { + imageBuffer := createImageBuffer(t) + defer imageBuffer.Destroy() + got := imageBuffer.Clear() + require.True(t, got) +} + +func TestImageBuffer_SetRawData(t *testing.T) { + imageBuffer := createImageBuffer(t) + defer imageBuffer.Destroy() + + width, height := 2, 2 + img1 := image.NewNRGBA(image.Rect(0, 0, width, height)) + img1.SetNRGBA(0, 0, color.NRGBA{R: 255, G: 0, B: 0, A: 255}) + img1.SetNRGBA(1, 0, color.NRGBA{R: 0, G: 255, B: 0, A: 255}) + img1.SetNRGBA(0, 1, color.NRGBA{R: 0, G: 0, B: 255, A: 255}) + img1.SetNRGBA(1, 1, color.NRGBA{R: 255, G: 255, B: 255, A: 255}) + + got := imageBuffer.SetRawData(img1) + require.True(t, got) + + img2 := imageBuffer.GetByRawData() + require.NotNil(t, img2) + require.Equal(t, img1, img2) +} From db40822478115641dd3fa188d2e2c125f086a8c6 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 18:42:38 +0800 Subject: [PATCH 20/35] perf: `NewImageListBuffer` --- internal/buffer/image_list_buffer.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/buffer/image_list_buffer.go b/internal/buffer/image_list_buffer.go index 4eb2a62..55b6918 100644 --- a/internal/buffer/image_list_buffer.go +++ b/internal/buffer/image_list_buffer.go @@ -16,6 +16,9 @@ type ImageListBuffer struct { func NewImageListBuffer() *ImageListBuffer { handle := C.MaaImageListBufferCreate() + if handle == nil { + return nil + } return &ImageListBuffer{ handle: handle, } @@ -65,7 +68,7 @@ func (il *ImageListBuffer) GetAll() []image.Image { return images } -func (il *ImageListBuffer) Append(value ImageBuffer) bool { +func (il *ImageListBuffer) Append(value *ImageBuffer) bool { return C.MaaImageListBufferAppend( il.handle, (*C.MaaImageBuffer)(value.Handle()), From 229ee44c9e72ea7c16efdb7695349d9318bf5ba6 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 18:57:28 +0800 Subject: [PATCH 21/35] test: add image list buffer test --- internal/buffer/image_list_buffer_test.go | 143 ++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 internal/buffer/image_list_buffer_test.go diff --git a/internal/buffer/image_list_buffer_test.go b/internal/buffer/image_list_buffer_test.go new file mode 100644 index 0000000..a91f15e --- /dev/null +++ b/internal/buffer/image_list_buffer_test.go @@ -0,0 +1,143 @@ +package buffer + +import ( + "github.com/stretchr/testify/require" + "image" + "image/color" + "testing" +) + +func createImageListBuffer(t *testing.T) *ImageListBuffer { + imageListBuffer := NewImageListBuffer() + require.NotNil(t, imageListBuffer) + return imageListBuffer +} + +func TestNewImageListBuffer(t *testing.T) { + imageListBuffer := createImageListBuffer(t) + imageListBuffer.Destroy() +} + +func TestImageListBuffer_Handle(t *testing.T) { + imageListBuffer := createImageListBuffer(t) + defer imageListBuffer.Destroy() + handle := imageListBuffer.Handle() + require.NotNil(t, handle) +} + +func TestImageListBuffer_IsEmpty(t *testing.T) { + imageListBuffer := createImageListBuffer(t) + defer imageListBuffer.Destroy() + got := imageListBuffer.IsEmpty() + require.True(t, got) +} + +func TestImageListBuffer_Clear(t *testing.T) { + imageListBuffer := createImageListBuffer(t) + defer imageListBuffer.Destroy() + got := imageListBuffer.Clear() + require.True(t, got) +} + +func TestImageListBuffer_Append(t *testing.T) { + imageListBuffer := createImageListBuffer(t) + defer imageListBuffer.Destroy() + + imageBuffer := createImageBuffer(t) + defer imageBuffer.Destroy() + + width, height := 2, 2 + img1 := image.NewNRGBA(image.Rect(0, 0, width, height)) + img1.SetNRGBA(0, 0, color.NRGBA{R: 255, G: 0, B: 0, A: 255}) + img1.SetNRGBA(1, 0, color.NRGBA{R: 0, G: 255, B: 0, A: 255}) + img1.SetNRGBA(0, 1, color.NRGBA{R: 0, G: 0, B: 255, A: 255}) + img1.SetNRGBA(1, 1, color.NRGBA{R: 255, G: 255, B: 255, A: 255}) + + got := imageBuffer.SetRawData(img1) + require.True(t, got) + + appended := imageListBuffer.Append(imageBuffer) + require.True(t, appended) + + got2 := imageListBuffer.IsEmpty() + require.False(t, got2) + + img2 := imageListBuffer.Get(0) + require.NotNil(t, img2) + require.Equal(t, img1, img2) +} + +func TestImageListBuffer_Remove(t *testing.T) { + imageListBuffer := createImageListBuffer(t) + defer imageListBuffer.Destroy() + + imageBuffer := createImageBuffer(t) + defer imageBuffer.Destroy() + + width, height := 2, 2 + img := image.NewNRGBA(image.Rect(0, 0, width, height)) + img.SetNRGBA(0, 0, color.NRGBA{R: 255, G: 0, B: 0, A: 255}) + img.SetNRGBA(1, 0, color.NRGBA{R: 0, G: 255, B: 0, A: 255}) + img.SetNRGBA(0, 1, color.NRGBA{R: 0, G: 0, B: 255, A: 255}) + img.SetNRGBA(1, 1, color.NRGBA{R: 255, G: 255, B: 255, A: 255}) + + got := imageBuffer.SetRawData(img) + require.True(t, got) + + appended := imageListBuffer.Append(imageBuffer) + require.True(t, appended) + + removed := imageListBuffer.Remove(0) + require.True(t, removed) + + got2 := imageListBuffer.IsEmpty() + require.True(t, got2) +} + +func TestImageListBuffer_Size(t *testing.T) { + imageListBuffer := createImageListBuffer(t) + defer imageListBuffer.Destroy() + + imageBuffer := createImageBuffer(t) + defer imageBuffer.Destroy() + + width, height := 2, 2 + img1 := image.NewNRGBA(image.Rect(0, 0, width, height)) + img1.SetNRGBA(0, 0, color.NRGBA{R: 255, G: 0, B: 0, A: 255}) + img1.SetNRGBA(1, 0, color.NRGBA{R: 0, G: 255, B: 0, A: 255}) + img1.SetNRGBA(0, 1, color.NRGBA{R: 0, G: 0, B: 255, A: 255}) + img1.SetNRGBA(1, 1, color.NRGBA{R: 255, G: 255, B: 255, A: 255}) + + got := imageBuffer.SetRawData(img1) + require.True(t, got) + + appended := imageListBuffer.Append(imageBuffer) + require.True(t, appended) + + size := imageListBuffer.Size() + require.Equal(t, uint64(1), size) +} + +func TestImageListBuffer_GetAll(t *testing.T) { + imageListBuffer := createImageListBuffer(t) + defer imageListBuffer.Destroy() + + imageBuffer := createImageBuffer(t) + defer imageBuffer.Destroy() + + width, height := 2, 2 + img1 := image.NewNRGBA(image.Rect(0, 0, width, height)) + img1.SetNRGBA(0, 0, color.NRGBA{R: 255, G: 0, B: 0, A: 255}) + img1.SetNRGBA(1, 0, color.NRGBA{R: 0, G: 255, B: 0, A: 255}) + img1.SetNRGBA(0, 1, color.NRGBA{R: 0, G: 0, B: 255, A: 255}) + img1.SetNRGBA(1, 1, color.NRGBA{R: 255, G: 255, B: 255, A: 255}) + + got := imageBuffer.SetRawData(img1) + require.True(t, got) + + appended := imageListBuffer.Append(imageBuffer) + require.True(t, appended) + + list := imageListBuffer.GetAll() + require.Len(t, list, 1) +} From a9eadf101bfc79880256dd39e520c6e1251d0968 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 19:06:58 +0800 Subject: [PATCH 22/35] perf: `NewRectBuffer` --- internal/buffer/rect_buffer.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/buffer/rect_buffer.go b/internal/buffer/rect_buffer.go index 0300d94..27a71f9 100644 --- a/internal/buffer/rect_buffer.go +++ b/internal/buffer/rect_buffer.go @@ -23,6 +23,9 @@ type RectBuffer struct { func NewRectBuffer() *RectBuffer { handle := C.MaaRectCreate() + if handle == nil { + return nil + } return &RectBuffer{ handle: handle, } From 238b16f03ad3103205d59f4627c7d5cde8bbee1b Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 19:07:08 +0800 Subject: [PATCH 23/35] test: add rect buffer test --- internal/buffer/react_buffer_test.go | 44 ++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 internal/buffer/react_buffer_test.go diff --git a/internal/buffer/react_buffer_test.go b/internal/buffer/react_buffer_test.go new file mode 100644 index 0000000..0b17a64 --- /dev/null +++ b/internal/buffer/react_buffer_test.go @@ -0,0 +1,44 @@ +package buffer + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func createRectBuffer(t *testing.T) *RectBuffer { + rectBuffer := NewRectBuffer() + require.NotNil(t, rectBuffer) + return rectBuffer +} + +func TestNewRectBuffer(t *testing.T) { + rectBuffer := createRectBuffer(t) + rectBuffer.Destroy() +} + +func TestRectBuffer_Handle(t *testing.T) { + rectBuffer := createRectBuffer(t) + defer rectBuffer.Destroy() + handle := rectBuffer.Handle() + require.NotNil(t, handle) +} + +func TestRectBuffer_Set(t *testing.T) { + rectBuffer := createRectBuffer(t) + defer rectBuffer.Destroy() + + rect1 := Rect{100, 200, 300, 400} + got := rectBuffer.Set(rect1) + require.True(t, got) + + x := rectBuffer.GetX() + require.Equal(t, rect1.X, x) + y := rectBuffer.GetY() + require.Equal(t, rect1.Y, y) + w := rectBuffer.GetW() + require.Equal(t, rect1.W, w) + h := rectBuffer.GetH() + require.Equal(t, rect1.H, h) + rect2 := rectBuffer.Get() + require.Equal(t, rect1, rect2) +} From 9a149131648a4c676b56bef350cb03469a41e9b8 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 19:18:15 +0800 Subject: [PATCH 24/35] fix: typo --- internal/buffer/{react_buffer_test.go => rect_buffer_test.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename internal/buffer/{react_buffer_test.go => rect_buffer_test.go} (100%) diff --git a/internal/buffer/react_buffer_test.go b/internal/buffer/rect_buffer_test.go similarity index 100% rename from internal/buffer/react_buffer_test.go rename to internal/buffer/rect_buffer_test.go From 43ef00eca099ff3aa0a9008aa8ec9779afb07655 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 19:23:43 +0800 Subject: [PATCH 25/35] perf: `NewStringBuffer` --- internal/buffer/string_buffer.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/buffer/string_buffer.go b/internal/buffer/string_buffer.go index 12bb159..0493624 100644 --- a/internal/buffer/string_buffer.go +++ b/internal/buffer/string_buffer.go @@ -13,6 +13,9 @@ type StringBuffer struct { func NewStringBuffer() *StringBuffer { handle := C.MaaStringBufferCreate() + if handle == nil { + return nil + } return &StringBuffer{ handle: handle, } From 8ec38bab2cb26e0999faba1fe533b20046408124 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 19:23:54 +0800 Subject: [PATCH 26/35] test: add string buffer test --- internal/buffer/string_buffer_test.go | 71 +++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 internal/buffer/string_buffer_test.go diff --git a/internal/buffer/string_buffer_test.go b/internal/buffer/string_buffer_test.go new file mode 100644 index 0000000..d8850dc --- /dev/null +++ b/internal/buffer/string_buffer_test.go @@ -0,0 +1,71 @@ +package buffer + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func createStringBuffer(t *testing.T) *StringBuffer { + stringBuffer := NewStringBuffer() + require.NotNil(t, stringBuffer) + return stringBuffer +} + +func TestNewStringBuffer(t *testing.T) { + stringBuffer := createStringBuffer(t) + stringBuffer.Destroy() +} + +func TestStringBuffer_Handle(t *testing.T) { + stringBuffer := createStringBuffer(t) + defer stringBuffer.Destroy() + handle := stringBuffer.Handle() + require.NotNil(t, handle) +} + +func TestStringBuffer_IsEmpty(t *testing.T) { + stringBuffer := createStringBuffer(t) + defer stringBuffer.Destroy() + got := stringBuffer.IsEmpty() + require.True(t, got) +} + +func TestStringBuffer_Clear(t *testing.T) { + stringBuffer := createStringBuffer(t) + defer stringBuffer.Destroy() + got := stringBuffer.Clear() + require.True(t, got) +} + +func TestStringBuffer_Set(t *testing.T) { + stringBuffer := createStringBuffer(t) + defer stringBuffer.Destroy() + str1 := "test" + got := stringBuffer.Set(str1) + require.True(t, got) + + str2 := stringBuffer.Get() + require.Equal(t, str1, str2) +} + +func TestStringBuffer_Size(t *testing.T) { + stringBuffer := createStringBuffer(t) + defer stringBuffer.Destroy() + str := "test" + got := stringBuffer.Set(str) + require.True(t, got) + + size := stringBuffer.Size() + require.Equal(t, uint64(len(str)), size) +} + +func TestStringBuffer_SetWithSize(t *testing.T) { + stringBuffer := createStringBuffer(t) + defer stringBuffer.Destroy() + str1 := "test" + got := stringBuffer.SetWithSize(str1, uint64(len(str1))) + require.True(t, got) + + str2 := stringBuffer.Get() + require.Equal(t, str1, str2) +} From 0137553c865769a591cce45c4822f6fe6806ae34 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 20:22:38 +0800 Subject: [PATCH 27/35] perf: `NewStringListBuffer` --- internal/buffer/string_list_buffer.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/buffer/string_list_buffer.go b/internal/buffer/string_list_buffer.go index 2aa3386..649482f 100644 --- a/internal/buffer/string_list_buffer.go +++ b/internal/buffer/string_list_buffer.go @@ -13,6 +13,9 @@ type StringListBuffer struct { func NewStringListBuffer() *StringListBuffer { handle := C.MaaStringListBufferCreate() + if handle == nil { + return nil + } return &StringListBuffer{ handle: handle, } From cc08633477186691885006aa2890182bb16fc7f3 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 20:22:55 +0800 Subject: [PATCH 28/35] test: add string list buffer test --- internal/buffer/string_list_buffer_test.go | 114 +++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 internal/buffer/string_list_buffer_test.go diff --git a/internal/buffer/string_list_buffer_test.go b/internal/buffer/string_list_buffer_test.go new file mode 100644 index 0000000..840f19b --- /dev/null +++ b/internal/buffer/string_list_buffer_test.go @@ -0,0 +1,114 @@ +package buffer + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func createStringListBuffer(t *testing.T) *StringListBuffer { + stringListBuffer := NewStringListBuffer() + require.NotNil(t, stringListBuffer) + return stringListBuffer +} + +func TestNewStringListBuffer(t *testing.T) { + stringListBuffer := createStringListBuffer(t) + stringListBuffer.Destroy() +} + +func TestStringListBuffer_Handle(t *testing.T) { + stringListBuffer := createStringListBuffer(t) + defer stringListBuffer.Destroy() + handle := stringListBuffer.Handle() + require.NotNil(t, handle) +} + +func TestStringListBuffer_IsEmpty(t *testing.T) { + stringListBuffer := createStringListBuffer(t) + defer stringListBuffer.Destroy() + got := stringListBuffer.IsEmpty() + require.True(t, got) +} + +func TestStringListBuffer_Clear(t *testing.T) { + stringListBuffer := createStringListBuffer(t) + defer stringListBuffer.Destroy() + got := stringListBuffer.Clear() + require.True(t, got) +} + +func TestStringListBuffer_Append(t *testing.T) { + stringListBuffer := createStringListBuffer(t) + defer stringListBuffer.Destroy() + + stringBuffer := createStringBuffer(t) + str1 := "test" + got1 := stringBuffer.Set(str1) + require.True(t, got1) + + got2 := stringListBuffer.Append(stringBuffer) + require.True(t, got2) + + got3 := stringListBuffer.IsEmpty() + require.False(t, got3) + + str2 := stringListBuffer.Get(0) + require.Equal(t, str1, str2) +} + +func TestStringListBuffer_Remove(t *testing.T) { + stringListBuffer := createStringListBuffer(t) + defer stringListBuffer.Destroy() + + stringBuffer := createStringBuffer(t) + str1 := "test" + got1 := stringBuffer.Set(str1) + require.True(t, got1) + + got2 := stringListBuffer.Append(stringBuffer) + require.True(t, got2) + + removed := stringListBuffer.Remove(0) + require.True(t, removed) + + got3 := stringListBuffer.IsEmpty() + require.True(t, got3) +} + +func TestStringListBuffer_Size(t *testing.T) { + stringListBuffer := createStringListBuffer(t) + defer stringListBuffer.Destroy() + + stringBuffer := createStringBuffer(t) + str1 := "test" + got1 := stringBuffer.Set(str1) + require.True(t, got1) + + got2 := stringListBuffer.Append(stringBuffer) + require.True(t, got2) + + got3 := stringListBuffer.IsEmpty() + require.False(t, got3) + + size := stringListBuffer.Size() + require.Equal(t, uint64(1), size) +} + +func TestStringListBuffer_GetAll(t *testing.T) { + stringListBuffer := createStringListBuffer(t) + defer stringListBuffer.Destroy() + + stringBuffer := createStringBuffer(t) + str1 := "test" + got1 := stringBuffer.Set(str1) + require.True(t, got1) + + got2 := stringListBuffer.Append(stringBuffer) + require.True(t, got2) + + got3 := stringListBuffer.IsEmpty() + require.False(t, got3) + + list := stringListBuffer.GetAll() + require.Len(t, list, 1) +} From a96ae6ec0ab31843b4b4882ce4a808ea31b47ab1 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 21:27:55 +0800 Subject: [PATCH 29/35] fix: empty log dir path --- option.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/option.go b/option.go index 4bfc3c6..6d019be 100644 --- a/option.go +++ b/option.go @@ -48,6 +48,9 @@ const ( // SetLogDir sets the log directory. func SetLogDir(path string) bool { + if path == "" { + return false + } cPath := C.CString(path) defer C.free(unsafe.Pointer(cPath)) return C.MaaSetGlobalOption(C.int32_t(GlobalOptionLogDir), C.MaaOptionValue(cPath), C.uint64_t(len(path))) != 0 From 6571ae7f3c7350c1b606493b5997973534b7ae8f Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 21:28:06 +0800 Subject: [PATCH 30/35] test: add option test --- option_test.go | 192 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 option_test.go diff --git a/option_test.go b/option_test.go new file mode 100644 index 0000000..4452a5f --- /dev/null +++ b/option_test.go @@ -0,0 +1,192 @@ +package maa + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func TestSetLogDir(t *testing.T) { + testCases := []struct { + name string + path string + expected bool + }{ + { + name: "ValidPath", + path: "./test/debug", + expected: true, + }, + { + name: "EmptyPath", + path: "", + expected: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := SetLogDir(tc.path) + require.Equal(t, tc.expected, result) + }) + } +} + +func TestSetSaveDraw(t *testing.T) { + testCases := []struct { + name string + enabled bool + expected bool + }{ + { + name: "EnableSaveDraw", + enabled: true, + expected: true, + }, + { + name: "DisableSaveDraw", + enabled: false, + expected: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := SetSaveDraw(tc.enabled) + require.Equal(t, tc.expected, result) + }) + } +} + +func TestSetRecording(t *testing.T) { + testCases := []struct { + name string + enabled bool + expected bool + }{ + { + name: "EnableRecording", + enabled: true, + expected: true, + }, + { + name: "DisableRecording", + enabled: false, + expected: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := SetRecording(tc.enabled) + require.Equal(t, tc.expected, result) + }) + } +} + +func TestSetStdoutLevel(t *testing.T) { + testCases := []struct { + name string + level LoggingLevel + expected bool + }{ + { + name: "SetLevelOff", + level: LoggingLevelOff, + expected: true, + }, + { + name: "SetLevelFatal", + level: LoggingLevelFatal, + expected: true, + }, + { + name: "SetLevelError", + level: LoggingLevelError, + expected: true, + }, + { + name: "SetLevelWarn", + level: LoggingLevelWarn, + expected: true, + }, + { + name: "SetLevelInfo", + level: LoggingLevelInfo, + expected: true, + }, + { + name: "SetLevelDebug", + level: LoggingLevelDebug, + expected: true, + }, + { + name: "SetLevelTrace", + level: LoggingLevelTrace, + expected: true, + }, + { + name: "SetLevelAll", + level: LoggingLevelAll, + expected: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := SetStdoutLevel(tc.level) + require.Equal(t, tc.expected, result) + }) + } +} + +func TestSetShowHitDraw(t *testing.T) { + testCases := []struct { + name string + enabled bool + expected bool + }{ + { + name: "EnableShowHitDraw", + enabled: true, + expected: true, + }, + { + name: "DisableShowHitDraw", + enabled: false, + expected: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := SetShowHitDraw(tc.enabled) + require.Equal(t, tc.expected, result) + }) + } +} + +func TestSetDebugMode(t *testing.T) { + testCases := []struct { + name string + enabled bool + expected bool + }{ + { + name: "EnableDebugMode", + enabled: true, + expected: true, + }, + { + name: "DisableDebugMode", + enabled: false, + expected: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := SetDebugMode(tc.enabled) + require.Equal(t, tc.expected, result) + }) + } +} From 6516d8209337f965b716fdcc248aa24fdd9e89c8 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 21:53:15 +0800 Subject: [PATCH 31/35] docs: update maa framework badge --- README.md | 4 ++-- README_zh.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ef67182..ed27fdc 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ go reference - - maa framework + + maa framework

diff --git a/README_zh.md b/README_zh.md index 34526d3..578d24c 100644 --- a/README_zh.md +++ b/README_zh.md @@ -11,8 +11,8 @@ go reference - - maa framework + + maa framework

From 3656ebd300aedb4af9a6f3141e56a65d0379d31e Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 22:32:12 +0800 Subject: [PATCH 32/35] ci: refactor: release --- .github/workflows/release.yml | 26 -------------------------- .github/workflows/test.yml | 17 ++++++++++++++++- 2 files changed, 16 insertions(+), 27 deletions(-) delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index f851bf6..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: release - -on: - push: - tags: - - "v*" - - workflow_dispatch: - -jobs: - meta: - uses: ./.github/workflows/meta.yml - - release: - if: ${{ needs.meta.outputs.is_release == 'true' }} - needs: meta - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Release - uses: softprops/action-gh-release@v2 - with: - tag_name: ${{ needs.meta.outputs.tag }} \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 797e604..1aea494 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,6 +2,8 @@ name: test on: push: + tags: + - "v*" branches: - "**" @@ -9,6 +11,8 @@ on: branches: - "**" + workflow_dispatch: + jobs: windows: runs-on: windows-latest @@ -173,4 +177,15 @@ jobs: if: always() with: name: MAA-macos-${{ matrix.arch }}-full_log - path: "test/debug" \ No newline at end of file + path: "test/debug" + + release: + if: ${{ needs.meta.outputs.is_release == 'true' }} + needs: [meta, windows, ubuntu, macos] + runs-on: ubuntu-latest + + steps: + - name: Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ needs.meta.outputs.tag }} \ No newline at end of file From 2fedf142be48333de86a054efcecce2bcb931a0e Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 22:34:34 +0800 Subject: [PATCH 33/35] ci: fix --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1aea494..57d39a7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,6 +14,9 @@ on: workflow_dispatch: jobs: + meta: + uses: ./.github/workflows/meta.yml + windows: runs-on: windows-latest strategy: From 191ad49d2b3eeb36f94bde7b2cbfb86049a2e66b Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 22:41:50 +0800 Subject: [PATCH 34/35] docs: update examples --- README.md | 2 +- README_zh.md | 2 +- examples/custom-action/main.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ed27fdc..93f8503 100644 --- a/README.md +++ b/README.md @@ -289,7 +289,7 @@ func main() { type MyAct struct{} -func (a *MyAct) Run(_ *maa.Context, arg *maa.CustomActionArg) bool { +func (a *MyAct) Run(_ *maa.Context, _ *maa.CustomActionArg) bool { return true } diff --git a/README_zh.md b/README_zh.md index 578d24c..e4450ea 100644 --- a/README_zh.md +++ b/README_zh.md @@ -288,7 +288,7 @@ func main() { type MyAct struct{} -func (a *MyAct) Run(_ *maa.Context, arg *maa.CustomActionArg) bool { +func (a *MyAct) Run(_ *maa.Context, _ *maa.CustomActionArg) bool { return true } diff --git a/examples/custom-action/main.go b/examples/custom-action/main.go index bc112ba..ebfec11 100644 --- a/examples/custom-action/main.go +++ b/examples/custom-action/main.go @@ -43,6 +43,6 @@ func main() { type MyAct struct{} -func (a *MyAct) Run(_ *maa.Context, arg *maa.CustomActionArg) bool { +func (a *MyAct) Run(_ *maa.Context, _ *maa.CustomActionArg) bool { return true } From 888860e2baecebee8a16882d9d23ba2674f9c268 Mon Sep 17 00:00:00 2001 From: dongwlin Date: Sun, 22 Sep 2024 22:47:26 +0800 Subject: [PATCH 35/35] chore: rename --- context.go | 2 +- controller.go | 2 +- custom_controller.go | 2 +- custom_recognition.go | 2 +- internal/buffer/image_buffer.go | 8 ++++---- internal/buffer/image_buffer_test.go | 6 +++--- internal/buffer/image_list_buffer.go | 2 +- internal/buffer/image_list_buffer_test.go | 8 ++++---- tasker.go | 2 +- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/context.go b/context.go index 8a123b4..97007b5 100644 --- a/context.go +++ b/context.go @@ -54,7 +54,7 @@ func (ctx *Context) runRecognition(entry, override string, img image.Image) *Rec cOverride := C.CString(override) defer C.free(unsafe.Pointer(cOverride)) imgBuf := buffer.NewImageBuffer() - imgBuf.SetRawData(img) + imgBuf.Set(img) defer imgBuf.Destroy() recId := int64(C.MaaContextRunRecognition(ctx.handle, cEntry, cOverride, (*C.MaaImageBuffer)(imgBuf.Handle()))) diff --git a/controller.go b/controller.go index dcce0e5..c1a3cfe 100644 --- a/controller.go +++ b/controller.go @@ -446,7 +446,7 @@ func (c *controller) CacheImage() image.Image { return nil } - img := imgBuffer.GetByRawData() + img := imgBuffer.Get() return img } diff --git a/custom_controller.go b/custom_controller.go index 56bc030..e162614 100644 --- a/custom_controller.go +++ b/custom_controller.go @@ -176,7 +176,7 @@ func _ScreencapAgent(handleArg unsafe.Pointer, imgBuffer *C.MaaImageBuffer) C.ui img, captured := ctrl.Screencap() if captured { imgImgBuffer := buffer.NewImageBufferByHandle(unsafe.Pointer(imgBuffer)) - if ok := imgImgBuffer.SetRawData(img); ok { + if ok := imgImgBuffer.Set(img); ok { return C.uint8_t(1) } } diff --git a/custom_recognition.go b/custom_recognition.go index 8970b8a..710a22e 100644 --- a/custom_recognition.go +++ b/custom_recognition.go @@ -81,7 +81,7 @@ func _MaaCustomRecognitionCallbackAgent( tasker := context.GetTasker() taskDetail := tasker.getTaskDetail(int64(taskId)) imgBuffer := buffer.NewImageBufferByHandle(unsafe.Pointer(img)) - imgImg := imgBuffer.GetByRawData() + imgImg := imgBuffer.Get() ret, ok := recognizer.Run( &Context{handle: ctx}, diff --git a/internal/buffer/image_buffer.go b/internal/buffer/image_buffer.go index 78482c7..7ed6917 100644 --- a/internal/buffer/image_buffer.go +++ b/internal/buffer/image_buffer.go @@ -48,8 +48,8 @@ func (i *ImageBuffer) Clear() bool { return C.MaaImageBufferClear(i.handle) != 0 } -// GetByRawData retrieves the image from raw data stored in the buffer. -func (i *ImageBuffer) GetByRawData() image.Image { +// Get retrieves the image from raw data stored in the buffer. +func (i *ImageBuffer) Get() image.Image { rawData := i.getRawData() if rawData == nil { return nil @@ -71,8 +71,8 @@ func (i *ImageBuffer) GetByRawData() image.Image { return img } -// SetRawData converts an image.Image to raw data and sets it in the buffer. -func (i *ImageBuffer) SetRawData(img image.Image) bool { +// Set converts an image.Image to raw data and sets it in the buffer. +func (i *ImageBuffer) Set(img image.Image) bool { width := img.Bounds().Dx() height := img.Bounds().Dy() imageType := int32(16) // CV_8UC3 diff --git a/internal/buffer/image_buffer_test.go b/internal/buffer/image_buffer_test.go index 5763c19..b758def 100644 --- a/internal/buffer/image_buffer_test.go +++ b/internal/buffer/image_buffer_test.go @@ -39,7 +39,7 @@ func TestImageBuffer_Clear(t *testing.T) { require.True(t, got) } -func TestImageBuffer_SetRawData(t *testing.T) { +func TestImageBuffer_Set(t *testing.T) { imageBuffer := createImageBuffer(t) defer imageBuffer.Destroy() @@ -50,10 +50,10 @@ func TestImageBuffer_SetRawData(t *testing.T) { img1.SetNRGBA(0, 1, color.NRGBA{R: 0, G: 0, B: 255, A: 255}) img1.SetNRGBA(1, 1, color.NRGBA{R: 255, G: 255, B: 255, A: 255}) - got := imageBuffer.SetRawData(img1) + got := imageBuffer.Set(img1) require.True(t, got) - img2 := imageBuffer.GetByRawData() + img2 := imageBuffer.Get() require.NotNil(t, img2) require.Equal(t, img1, img2) } diff --git a/internal/buffer/image_list_buffer.go b/internal/buffer/image_list_buffer.go index 55b6918..95c6fea 100644 --- a/internal/buffer/image_list_buffer.go +++ b/internal/buffer/image_list_buffer.go @@ -55,7 +55,7 @@ func (il *ImageListBuffer) Get(index uint64) image.Image { img := &ImageBuffer{ handle: handle, } - return img.GetByRawData() + return img.Get() } func (il *ImageListBuffer) GetAll() []image.Image { diff --git a/internal/buffer/image_list_buffer_test.go b/internal/buffer/image_list_buffer_test.go index a91f15e..580ab8a 100644 --- a/internal/buffer/image_list_buffer_test.go +++ b/internal/buffer/image_list_buffer_test.go @@ -53,7 +53,7 @@ func TestImageListBuffer_Append(t *testing.T) { img1.SetNRGBA(0, 1, color.NRGBA{R: 0, G: 0, B: 255, A: 255}) img1.SetNRGBA(1, 1, color.NRGBA{R: 255, G: 255, B: 255, A: 255}) - got := imageBuffer.SetRawData(img1) + got := imageBuffer.Set(img1) require.True(t, got) appended := imageListBuffer.Append(imageBuffer) @@ -81,7 +81,7 @@ func TestImageListBuffer_Remove(t *testing.T) { img.SetNRGBA(0, 1, color.NRGBA{R: 0, G: 0, B: 255, A: 255}) img.SetNRGBA(1, 1, color.NRGBA{R: 255, G: 255, B: 255, A: 255}) - got := imageBuffer.SetRawData(img) + got := imageBuffer.Set(img) require.True(t, got) appended := imageListBuffer.Append(imageBuffer) @@ -108,7 +108,7 @@ func TestImageListBuffer_Size(t *testing.T) { img1.SetNRGBA(0, 1, color.NRGBA{R: 0, G: 0, B: 255, A: 255}) img1.SetNRGBA(1, 1, color.NRGBA{R: 255, G: 255, B: 255, A: 255}) - got := imageBuffer.SetRawData(img1) + got := imageBuffer.Set(img1) require.True(t, got) appended := imageListBuffer.Append(imageBuffer) @@ -132,7 +132,7 @@ func TestImageListBuffer_GetAll(t *testing.T) { img1.SetNRGBA(0, 1, color.NRGBA{R: 0, G: 0, B: 255, A: 255}) img1.SetNRGBA(1, 1, color.NRGBA{R: 255, G: 255, B: 255, A: 255}) - got := imageBuffer.SetRawData(img1) + got := imageBuffer.Set(img1) require.True(t, got) appended := imageListBuffer.Append(imageBuffer) diff --git a/tasker.go b/tasker.go index c2967de..a0ca65d 100644 --- a/tasker.go +++ b/tasker.go @@ -173,7 +173,7 @@ func (t *Tasker) getRecognitionDetail(recId int64) *RecognitionDetail { return nil } - rawImg := raw.GetByRawData() + rawImg := raw.Get() DrawImages := draws.GetAll() return &RecognitionDetail{