diff --git a/README.md b/README.md index 05b87ad..513c99c 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,34 @@ # 简介 -JMacro使用Java Robot工具实现的自动化/脚本脚手架,屏幕找图,定位,模拟人操作鼠标、键盘等基本事件。 +JMacro使用Java Robot工具实现的脚本/自动化脚手架,屏幕找图,定位,模拟人操作鼠标、键盘等基本事件。 -#背景 +# 背景 +起初是在玩一款经营类小游戏中有了想法;其中有着大量的重复工作,例如领取奖励、领取宝箱、野区采矿、出击野怪等基本操作。 +因此曾想过使用成熟的方案如按键精灵,因为很久以前也曾用过其制作的辅助工具,不过记得其在某些杀毒软件下是报毒,且例如腾讯类 +大型游戏有安全检测直接不通过,是因为《按键精灵》的典型特征。因此放弃的此方案。 +后来在想能否使用java来写一个脚本/自动化机器人了?因为我自己就是一位java开发人员;语法也熟悉;实现上也会更加的灵活;这一想就去调查 +一番,发现也确实有人有这个想法,但却一直未找到成熟的框架或依赖库。想想也对,这本就不是java领域的特长。 +所以最终决定自己编写一款简易脚手架,并开源共享。 -###环境依赖 +## 开发环境 +idea + +## 环境依赖 jdk1.8 -### 构建工具 +## 构建工具 Maven 3+ -### 依赖说明 -Hutool:一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率 +## 依赖说明 +### Hutool +使用了其中非常方便的api +### jintellitype +用于注册热键的库,运行时鼠标可能不方便操作,只能通过热键来结束。 +### javafx-maven-plugin +程序实现了一个简单的UI控制台,用于控制运行、停止、和开发调试工具。通过插件将jar打包为windows下可直接运行的程序包。这样可以让不安装jre和开发工具的电脑也能使用。 +### maven-antrun-plugin +打包图例资源文件 ##打包EXE可执行文件 ``` diff --git a/pom.xml b/pom.xml index f319a28..ee2953a 100644 --- a/pom.xml +++ b/pom.xml @@ -52,22 +52,12 @@ - ${artifactId}-${version} - src/main/java src/main/resources - - - ${basedir}/src/main/resources/lib - BOOT-INF/lib/ - - *.jar - - diff --git a/src/main/java/xyz/wbsite/jmacro/JMacro.java b/src/main/java/xyz/wbsite/jmacro/JMacro.java index 9d202af..e2f78f2 100644 --- a/src/main/java/xyz/wbsite/jmacro/JMacro.java +++ b/src/main/java/xyz/wbsite/jmacro/JMacro.java @@ -345,20 +345,9 @@ public abstract class JMacro { * * @param pic 图片 * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * @return 匹配区域 */ public ViewRect findPic(File pic, double minSimilar) { - return findPic(getFocusRect(), ImageUtil.load(pic), minSimilar); - } - - /** - * 全屏查找图片 - * - * @param pic 图片 - * @param minSimilar 最低相似度 - * @return 匹配图片区域 - */ - public ViewRect findPic(BufferedImage pic, double minSimilar) { return findPic(getFocusRect(), pic, minSimilar); } @@ -368,10 +357,20 @@ public abstract class JMacro { * @param viewRect 查找范围(不设时,取全屏) * @param pic 待查找图片 * @param minSimilar 相似度 - * @return 匹配图片区域 + * @return 匹配区域 */ public ViewRect findPic(ViewRect viewRect, File pic, double minSimilar) { - return findPic(viewRect, ImageUtil.load(pic), minSimilar); + if (!pic.exists()) { + Logger.error("[{}] does not exist!", pic.getAbsolutePath()); + return null; + } + if (!pic.isFile()) { + Logger.error("[{}] is not a file!", pic.getAbsolutePath()); + return null; + } + Logger.info("查找图片:{}", pic.getAbsolutePath()); + BufferedImage bufferedImage = ImageUtil.load(pic); + return findPic(viewRect, bufferedImage, minSimilar); } /** @@ -380,7 +379,7 @@ public abstract class JMacro { * @param viewRect 查找范围(不设时,取全屏) * @param pic 待查找图片 * @param minSimilar 相似度 - * @return 匹配图片区域 + * @return 匹配区域 */ public ViewRect findPic(ViewRect viewRect, BufferedImage pic, double minSimilar) { // 当聚焦区域为null时,默认全屏查找 @@ -450,48 +449,61 @@ public abstract class JMacro { } /** - * 查找图片 + * 等待并查找图片 * - * @param legend 图例 + * @param rect 查找区域 + * @param pic 图片 * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect findLegend(String legend, double minSimilar) { - return findLegend(Legend.inflate(legend), minSimilar); + public ViewRect waitAndFindPic(ViewRect rect, File pic, double minSimilar) { + return waitAndFindPic(rect, pic, minSimilar, defaultTimeOut); } /** - * 查找图片 + * 等待并查找图片 * - * @param legend 图例 + * @param pic 图片 * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect findLegend(Legend legend, double minSimilar) { - return findLegend(getFocusRect(), legend, minSimilar); + public ViewRect waitAndFindPic(File pic, double minSimilar) { + return waitAndFindPic(getFocusRect(), pic, minSimilar, defaultTimeOut); } /** - * 查找图例 + * 等待并查找图片 * - * @param legend 图例 + * @param pic 图片 * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * @param seconds 最长等待秒数 + * @return 匹配区域 */ - public ViewRect findLegend(ViewRect rect, String legend, double minSimilar) { - return findLegend(rect, Legend.inflate(legend), minSimilar); + public ViewRect waitAndFindPic(File pic, double minSimilar, long seconds) { + return waitAndFindPic(getFocusRect(), pic, minSimilar, seconds); } /** - * 查找图例 + * 等待并查找图片 * - * @param legend 图例 + * @param rect 查找区域 + * @param picFile 图片 * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * @param seconds 最长等待秒数 + * @return 匹配区域 */ - public ViewRect findLegend(ViewRect rect, Legend legend, double minSimilar) { - Logger.info("查找图例:{}", legend.getName()); - return findPic(rect, legend.getFile(), minSimilar); + public ViewRect waitAndFindPic(ViewRect rect, File picFile, double minSimilar, long seconds) { + Logger.info("等待并查找图片:{}", picFile.getAbsolutePath()); + BufferedImage pic = ImageUtil.load(picFile); + return TaskUtil.timeTask(() -> { + while (JMainService.getInstance().run) { + ViewRect result = findPic(rect, pic, minSimilar); + if (result != null) { + return result; + } + } + return null; + }, seconds, TimeUnit.SECONDS); } /** @@ -499,10 +511,10 @@ public abstract class JMacro { * * @param legend 图例 * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect waitAndFindLegend(Legend legend, double minSimilar, long seconds) { - return waitAndFindPic(legend.getFile(), minSimilar, seconds); + public ViewRect findLegend(String legend, double minSimilar) { + return findLegend(Legend.inflate(legend), minSimilar); } /** @@ -510,252 +522,217 @@ public abstract class JMacro { * * @param legend 图例 * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect waitAndFindLegend(ViewRect rect, Legend legend, double minSimilar, long seconds) { - return waitAndFindPic(rect, legend.getFile(), minSimilar, seconds); + public ViewRect findLegend(Legend legend, double minSimilar) { + return findLegend(getFocusRect(), legend, minSimilar); } /** - * 等待并查找图片 + * 查找图例 * - * @param pic 图片 + * @param legend 图例 * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect waitAndFindPic(File pic, double minSimilar) { - return waitAndFindPic(getFocusRect(), pic, minSimilar, defaultTimeOut); + public ViewRect findLegend(ViewRect rect, String legend, double minSimilar) { + return findLegend(rect, Legend.inflate(legend), minSimilar); } /** - * 等待并查找图片 + * 查找图例 * - * @param pic 图片 + * @param legend 图例 * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect waitAndFindPic(BufferedImage pic, double minSimilar) { - return waitAndFindPic(getFocusRect(), pic, minSimilar, defaultTimeOut); + public ViewRect findLegend(ViewRect rect, Legend legend, double minSimilar) { + Logger.info("查找图例:{}", legend.getName()); + return findPic(rect, legend.getImage(), minSimilar); } /** - * 等待并查找图片 + * 等待并查找图例 * - * @param pic 图片 + * @param legend 图例 * @param minSimilar 最低相似度 - * @param seconds 最长等待秒数 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect waitAndFindPic(File pic, double minSimilar, long seconds) { - return waitAndFindPic(getFocusRect(), pic, minSimilar, seconds); + public ViewRect waitAndFindLegend(ViewRect rect, Legend legend, double minSimilar, long seconds) { + Logger.info("等待并查找图例:{}", legend.getName()); + return TaskUtil.timeTask(() -> { + while (JMainService.getInstance().run) { + ViewRect result = findPic(rect, legend.getImage(), minSimilar); + if (result != null) { + return result; + } + } + return null; + }, seconds, TimeUnit.SECONDS); } /** - * 等待并查找图片 + * 等待并查找图例 * - * @param pic 图片 + * @param legend 图例 * @param minSimilar 最低相似度 - * @param seconds 最长等待秒数 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect waitAndFindPic(BufferedImage pic, double minSimilar, long seconds) { - return waitAndFindPic(getFocusRect(), pic, minSimilar, seconds); + public ViewRect waitAndFindLegend(ViewRect rect, String legend, double minSimilar, long seconds) { + return waitAndFindLegend(rect, Legend.inflate(legend), minSimilar, seconds); } /** - * 等待并查找图片 + * 等待并查找图例 * - * @param rect 查找区域 - * @param pic 图片 + * @param legend 图例 * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect waitAndFindPic(ViewRect rect, File pic, double minSimilar) { - return waitAndFindPic(rect, pic, minSimilar, defaultTimeOut); + public ViewRect waitAndFindLegend(Legend legend, double minSimilar, long seconds) { + return waitAndFindLegend(getFocusRect(), legend, minSimilar, seconds); } /** - * 等待并查找图片 + * 等待并查找图例 * - * @param rect 查找区域 - * @param pic 图片 + * @param legend 图例 * @param minSimilar 最低相似度 - * @param seconds 最长等待秒数 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect waitAndFindPic(ViewRect rect, File pic, double minSimilar, long seconds) { - return waitAndFindPic(rect, ImageUtil.load(pic), minSimilar, seconds); + public ViewRect waitAndFindLegend(String legend, double minSimilar, long seconds) { + return waitAndFindLegend(getFocusRect(), Legend.inflate(legend), minSimilar, seconds); } /** - * 等待并查找图片 + * 等待并查找图例 * - * @param rect 查找区域 - * @param pic 图片 + * @param legend 图例 * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect waitAndFindPic(ViewRect rect, BufferedImage pic, double minSimilar) { - return waitAndFindPic(rect, pic, minSimilar, defaultTimeOut); + public ViewRect waitAndFindLegend(Legend legend, double minSimilar) { + return waitAndFindLegend(getFocusRect(), legend, minSimilar, defaultTimeOut); } /** - * 等待并查找图片 + * 等待并查找图例 * - * @param rect 查找区域 - * @param pic 图片 + * @param legend 图例 * @param minSimilar 最低相似度 - * @param seconds 最长等待秒数 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect waitAndFindPic(ViewRect rect, BufferedImage pic, double minSimilar, long seconds) { - if (rect.getWidth() < pic.getWidth()) { - Logger.error("查找图片区域宽度{}小于图片宽度{}", rect.getWidth(), pic.getWidth()); - return null; - } - if (rect.getHeight() < pic.getHeight()) { - Logger.error("查找图片区域宽度{}小于图片宽度{}", rect.getHeight(), pic.getHeight()); - return null; - } - return TaskUtil.timeTask(() -> { - while (JMainService.getInstance().run) { - ViewRect result = findPic(rect, pic, minSimilar); - if (result != null) { - return result; - } - } - return null; - }, seconds, TimeUnit.SECONDS); + public ViewRect waitAndFindLegend(String legend, double minSimilar) { + return waitAndFindLegend(getFocusRect(), Legend.inflate(legend), minSimilar, defaultTimeOut); } /** - * 匹配图片 + * 匹配图例 * - * @param pic 图片 - * @param location 定位 + * @param legend 图例 * @param minSimilar 最低相似度 * @return 匹配图片 */ - public ViewRect matchPic(File pic, ViewPoint location, double minSimilar) { - if (!pic.exists()) { - Logger.error("file [{}] not exist", pic.getAbsolutePath()); - return null; - } - return matchPic(ImageUtil.load(pic), location, minSimilar); - } - - public ViewRect matchPic(BufferedImage pic, ViewPoint location, double minSimilar) { - ViewRect focusRect = getFocusRect(); - int offsetX = location.getX(); - int offsetY = location.getY(); + public ViewRect matchLegend(Legend legend, double minSimilar) { + BufferedImage image = ImageUtil.load(legend.getFile()); + // 获取图例相对坐标 + int offsetX = legend.getLocation().getX(); + int offsetY = legend.getLocation().getY(); + // 根据原点计算图例绝对坐标 ViewRect viewRect = new ViewRect(); - viewRect.setLeft(focusRect.getLeft() + offsetX); - viewRect.setTop(focusRect.getTop() + offsetY); - viewRect.setRight(viewRect.getLeft() + pic.getWidth()); - viewRect.setBottom(viewRect.getTop() + pic.getHeight()); - ImageUtil.show(viewRect); - return findPic(viewRect, pic, minSimilar); - } - - /** - * 等待并匹配图片 - * - * @param pic 图片 - * @param minSimilar 最低相似度 - * @return 匹配图片区域 - */ - public ViewRect waitAndMatchPic(File pic, ViewPoint location, double minSimilar) { - return waitAndMatchPic(ImageUtil.load(pic), location, minSimilar); + viewRect.setLeft(getFocusRect().getLeft() + offsetX); + viewRect.setTop(getFocusRect().getTop() + offsetY); + viewRect.setRight(viewRect.getLeft() + image.getWidth()); + viewRect.setBottom(viewRect.getTop() + image.getHeight()); + Logger.info("匹配图例:{},区域:{}", legend.getName(), viewRect); + return findPic(viewRect, image, minSimilar); } /** - * 等待并匹配图片 + * 匹配图例 * - * @param pic 图片 + * @param legend 图例 * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * @return 匹配图片 */ - public ViewRect waitAndMatchPic(BufferedImage pic, ViewPoint location, double minSimilar) { - return waitAndMatchPic(pic, location, minSimilar, defaultTimeOut); + public ViewRect matchLegend(String legend, double minSimilar) { + return matchLegend(Legend.inflate(legend), minSimilar); } /** - * 等待并匹配图片 + * 等待并匹配图例 * - * @param pic 图片 + * @param legend 图例 * @param minSimilar 最低相似度 * @param seconds 最长等待秒数 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect waitAndMatchPic(File pic, ViewPoint location, double minSimilar, long seconds) { - return waitAndMatchPic(ImageUtil.load(pic), location, minSimilar, seconds); + public ViewRect waitAndMatchLegend(Legend legend, double minSimilar, long seconds) { + Logger.info("等待并匹配图例:{}", legend.getName()); + return TaskUtil.timeTask(() -> { + while (JMainService.getInstance().run) { + ViewRect result = findPic(getFocusRect(), legend.getImage(), minSimilar); + if (result != null) { + return result; + } + } + return null; + }, seconds, TimeUnit.SECONDS); } /** - * 等待并匹配图片 + * 等待并匹配图例 * - * @param pic 图片 + * @param legend 图例 * @param minSimilar 最低相似度 * @param seconds 最长等待秒数 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect waitAndMatchPic(BufferedImage pic, ViewPoint location, double minSimilar, long seconds) { - return TaskUtil.timeTask(() -> { - while (JMainService.getInstance().run) { - ViewRect matchPic = matchPic(pic, location, minSimilar); - if (matchPic != null) { - return matchPic; - } - delayUnstable(); - } - return null; - }, seconds, TimeUnit.SECONDS); + public ViewRect waitAndMatchLegend(String legend, double minSimilar, long seconds) { + return waitAndMatchLegend(Legend.inflate(legend), minSimilar, seconds); } /** - * 匹配图例 + * 等待并匹配图例 * - * @param legends 图例 - * @param seconds 最长等待秒数 - * @return 匹配图片区域 + * @param legend 图例 + * @param minSimilar 最低相似度 + * @return 匹配区域 */ - public ViewRect[] waitAndMatchLegend(String[] legends, long seconds) { - return TaskUtil.timeTask(() -> { - while (JMainService.getInstance().run) { - ViewRect[] viewRects = matchLegend(legends); - for (ViewRect viewRect : viewRects) { - if (viewRect != null) { - return viewRects; - } - } - delayUnstable(); - } - return new ViewRect[legends.length]; - }, seconds, TimeUnit.SECONDS); + public ViewRect waitAndMatchLegend(String legend, double minSimilar) { + return waitAndMatchLegend(legend, minSimilar, defaultTimeOut); } /** - * 匹配图例 + * 等待并匹配图例 * - * @param legends 图例 - * @return 匹配图片 + * @param legend 图例 + * @param minSimilar 最低相似度 + * @return 匹配区域 */ - public ViewRect[] matchLegend(String... legends) { - return matchLegend(legends, 1.0); + public ViewRect waitAndMatchLegend(Legend legend, double minSimilar) { + return waitAndMatchLegend(legend, minSimilar, defaultTimeOut); } /** - * 匹配图例 + * 图例组合匹配,图例区域结果和入参长度一致,任意图例检测到后则会返回,其他未检测到的区域则为null + *

+ * 说明:一个操作之后可能会有多个预期结果,以发起【进攻】操作为例,可能会提示多种结果如下: + * 1.成功发起 + * 2.敌人已逃走 + * 3.兵力不足 + * 不同的操作返回结果,会有不同的后续操作;如果以获取某一结果去检测,考虑处理时间延迟等需要加上等待时间 + * 不同结果的获取就会依次串行,这样检查肯定会浪费大量检测时间。因此正对此情况做了并联检测机制。 * * @param legends 图例 * @param minSimilar 最低相似度 * @return 匹配图片 */ - public ViewRect[] matchLegend(String[] legends, double minSimilar) { + public ViewRect[] matchLegends(String[] legends, double minSimilar) { ViewRect[] viewRects = new ViewRect[legends.length]; for (int i = 0; i < legends.length; i++) { String legend = legends[i]; - viewRects[i] = matchLegend(Legend.inflate(legend), minSimilar); + viewRects[i] = matchLegend(legend, minSimilar); if (viewRects[i] != null) { return viewRects; } @@ -764,83 +741,73 @@ public abstract class JMacro { } /** - * 匹配图例 + * 多图例匹配调用优化 * - * @param legend 图例 - * @param minSimilar 最低相似度 + * @param legends 图例 * @return 匹配图片 */ - public ViewRect matchLegend(String legend, double minSimilar) { - return matchLegend(Legend.inflate(legend), minSimilar); + public ViewRect[] matchLegends(double minSimilar, String... legends) { + return matchLegends(legends, minSimilar); } /** - * 匹配图片 + * 等待并匹配图例组合 * - * @param legend 图例 + * @param legends 图例组 * @param minSimilar 最低相似度 - * @return 匹配图片 + * @param seconds 最长等待秒数 + * @return 匹配区域 */ - public ViewRect matchLegend(Legend legend, double minSimilar) { - if (minSimilar > 1) { - throw new RuntimeException("this minSimilar must be less than 1"); + public ViewRect[] waitAndMatchLegends(String[] legends, double minSimilar, long seconds) { + if (legends.length == 0) { + return new ViewRect[0]; } - int offsetX = legend.getLocation().getX(); - int offsetY = legend.getLocation().getY(); - ViewRect viewRect = new ViewRect(); - viewRect.setLeft(getFocusRect().getLeft() + offsetX); - viewRect.setTop(getFocusRect().getTop() + offsetY); - BufferedImage image = ImageUtil.load(legend.getFile()); - viewRect.setRight(viewRect.getLeft() + image.getWidth()); - viewRect.setBottom(viewRect.getTop() + image.getHeight()); - //ImageUtil.show(viewRect); - return findPic(viewRect, image, minSimilar); - } - - /** - * 等待并匹配图例 - * - * @param legend 图例 - * @param minSimilar 最低相似度 - * @return 匹配图片区域 - */ - public ViewRect waitAndMatchLegend(String legend, double minSimilar) { - return waitAndMatchLegend(Legend.inflate(legend), minSimilar); + Logger.info("等待并匹配图例组合:{}", String.join(",", legends)); + return TaskUtil.timeTask(() -> { + while (JMainService.getInstance().run) { + ViewRect[] viewRects = matchLegends(legends, minSimilar); + for (ViewRect viewRect : viewRects) { + if (viewRect != null) { + return viewRects; + } + } + } + return null; + }, seconds, TimeUnit.SECONDS); } /** - * 等待并匹配图例 + * 等待并匹配图例组合 * - * @param legend 图例 * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * @param seconds 最长等待秒数 + * @param legends 图例组 + * @return 匹配区域 */ - public ViewRect waitAndMatchLegend(Legend legend, double minSimilar) { - return waitAndMatchLegend(legend, minSimilar, defaultTimeOut); + public ViewRect[] waitAndMatchLegends(double minSimilar, long seconds, String... legends) { + return waitAndMatchLegends(legends, minSimilar, seconds); } /** - * 等待并匹配图例 + * 等待并匹配图例组合 * - * @param legend 图例 * @param minSimilar 最低相似度 - * @param seconds 最长等待秒数 - * @return 匹配图片区域 + * @param legends 图例组 + * @return 匹配区域 */ - public ViewRect waitAndMatchLegend(String legend, double minSimilar, long seconds) { - return waitAndMatchLegend(Legend.inflate(legend), minSimilar, seconds); + public ViewRect[] waitAndMatchLegends(double minSimilar, String... legends) { + return waitAndMatchLegends(legends, minSimilar, defaultTimeOut); } /** - * 等待并匹配图例 + * 等待并匹配图例组合 * - * @param legend 图例 + * @param legends 图例组 * @param minSimilar 最低相似度 - * @param seconds 最长等待秒数 - * @return 匹配图片区域 + * @return 匹配区域 */ - public ViewRect waitAndMatchLegend(Legend legend, double minSimilar, long seconds) { - return waitAndMatchPic(legend.getFile(), legend.getLocation(), minSimilar, seconds); + public ViewRect[] waitAndMatchLegends(String[] legends, double minSimilar) { + return waitAndMatchLegends(legends, minSimilar, defaultTimeOut); } /** @@ -863,7 +830,7 @@ public abstract class JMacro { * * @param color 色值坐标点 * @param seconds 最长等待秒数 - * @return 匹配图片区域 + * @return 匹配区域 */ public boolean waitAndMatchColor(ViewColor color, long seconds) { Boolean result = TaskUtil.timeTask(() -> { diff --git a/src/main/java/xyz/wbsite/jmacro/base/Legend.java b/src/main/java/xyz/wbsite/jmacro/base/Legend.java index 0ffdc3b..0e8627e 100644 --- a/src/main/java/xyz/wbsite/jmacro/base/Legend.java +++ b/src/main/java/xyz/wbsite/jmacro/base/Legend.java @@ -5,8 +5,10 @@ import cn.hutool.cache.CacheUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.ReUtil; +import xyz.wbsite.jmacro.util.ImageUtil; import xyz.wbsite.jmacro.util.Logger; +import java.awt.image.BufferedImage; import java.io.File; import java.util.List; @@ -111,6 +113,10 @@ public class Legend { return file; } + public BufferedImage getImage() { + return ImageUtil.load(this.file); + } + public String getName() { return name; } diff --git a/src/main/java/xyz/wbsite/jmacro/util/ImageUtil.java b/src/main/java/xyz/wbsite/jmacro/util/ImageUtil.java index 558c5ab..a05077b 100644 --- a/src/main/java/xyz/wbsite/jmacro/util/ImageUtil.java +++ b/src/main/java/xyz/wbsite/jmacro/util/ImageUtil.java @@ -1,14 +1,13 @@ package xyz.wbsite.jmacro.util; import cn.hutool.core.img.ImgUtil; +import cn.hutool.core.io.IoUtil; import xyz.wbsite.jmacro.JMainApplication; import xyz.wbsite.jmacro.JMainService; import xyz.wbsite.jmacro.base.ViewRect; import java.awt.*; import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.File; import java.util.ArrayList; import java.util.HashMap; @@ -127,19 +126,18 @@ public class ImageUtil { * @param image 图片 */ public static void show(BufferedImage image) { - int viewSize = 100; Image showImage = image; - // 图片太大时进行缩放显示 - if (image.getWidth() > viewSize || image.getHeight() > viewSize) { - if (image.getWidth() > image.getHeight()) { - showImage = ImgUtil.scale(showImage, 1.0f * viewSize / image.getWidth()); + // 图片宽高都大于预览窗口时进行缩放显示 + if (image.getWidth() > 192 || image.getHeight() > 108) { + // 宽高比大于预览窗口,适配宽, 否则适配高 + if (1D * image.getWidth() / image.getHeight() > 192D / 108D) { + showImage = ImgUtil.scale(showImage, 1.0f * 192 / image.getWidth()); } else { - showImage = ImgUtil.scale(showImage, 1.0f * viewSize / image.getHeight()); + showImage = ImgUtil.scale(showImage, 1.0f * 108 / image.getHeight()); } } - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - ImgUtil.write(showImage, "PNG", outputStream); - javafx.scene.image.Image image1 = new javafx.scene.image.Image(new ByteArrayInputStream(outputStream.toByteArray())); + byte[] bytes = ImgUtil.toBytes(showImage, "PNG"); + javafx.scene.image.Image image1 = new javafx.scene.image.Image(IoUtil.toStream(bytes)); JMainApplication.mainController.preview(image1); } } diff --git a/src/main/java/xyz/wbsite/jmacro/wjdr/MacroForWJDR.java b/src/main/java/xyz/wbsite/jmacro/wjdr/MacroForWJDR.java index c49eeba..f17ccb6 100644 --- a/src/main/java/xyz/wbsite/jmacro/wjdr/MacroForWJDR.java +++ b/src/main/java/xyz/wbsite/jmacro/wjdr/MacroForWJDR.java @@ -1,14 +1,14 @@ package xyz.wbsite.jmacro.wjdr; +import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import xyz.wbsite.jmacro.JMacro; import xyz.wbsite.jmacro.JMainService; -import xyz.wbsite.jmacro.base.Legend; import xyz.wbsite.jmacro.base.ViewRect; import xyz.wbsite.jmacro.util.Logger; +import xyz.wbsite.jmacro.wjdr.task.Task_定位城镇; import xyz.wbsite.jmacro.wjdr.task.Task_收留避难者; import xyz.wbsite.jmacro.wjdr.task.Task_自动采矿; -import xyz.wbsite.jmacro.wjdr.task.Task_返回城镇; import xyz.wbsite.jmacro.wjdr.task.Task_采矿被攻击; /** @@ -37,65 +37,63 @@ public class MacroForWJDR extends JMacro { @Override public synchronized ViewRect focus() { - // 定位窗口 - Logger.info("定位窗口"); - ViewRect mumu = findPic(Legend.inflate("慕慕_工具栏").getFile(), 0.95d); + Logger.info("聚焦窗口"); + ViewRect mumu = findLegend("慕慕_工具栏", 0.95d); + ViewRect rect = getScreenRect(); if (mumu == null) { - Logger.error("定位窗口失败"); - return null; + Logger.info("聚焦窗口失败,默认全屏"); + } else { + // 计算应用窗口返回 + rect.setLeft(mumu.getLeft() - 428); + rect.setTop(mumu.getBottom() + 7); + rect.setRight(mumu.getRight()); + rect.setBottom(mumu.getBottom() + 951); } - Logger.info("定位慕慕窗口成功"); - // 计算应用窗口返回 - ViewRect gameScreen = new ViewRect(); - gameScreen.setLeft(mumu.getLeft() - 428); - gameScreen.setTop(mumu.getBottom() + 7); - gameScreen.setRight(mumu.getRight()); - gameScreen.setBottom(mumu.getBottom() + 951); - Logger.info("应用窗口位置:" + gameScreen.toString()); - Logger.info("应用窗口大小:{}x{}", gameScreen.getRight() - gameScreen.getLeft(), gameScreen.getBottom() - gameScreen.getTop()); - return gameScreen; + Logger.info("聚焦窗口:" + rect.toString()); + Logger.info("聚焦窗口大小:{}x{}", rect.getRight() - rect.getLeft(), rect.getBottom() - rect.getTop()); + return rect; } @Override public void run() { - long startTime = System.currentTimeMillis(); - Logger.info("任务线程开始", DateUtil.date(startTime).toString("yyyy-MM-dd HH:mm:ss")); + DateTime current = DateUtil.date(); + String currentTime = current.toString("HH:mm:ss"); + Logger.info("工作时间:{}~{}", workStart, workEnd); + Logger.info("当前时间:{}", currentTime); + if (!DateUtil.parseTime(currentTime).isIn(DateUtil.parseTime(workStart), DateUtil.parseTime(workEnd))) { + Logger.info("当前时间为非工作时间,休眠待命!"); + delay(60 * 1000); + return; + } + Logger.info("当前时间为工作时间"); + Logger.info("任务线程开始", current.toString("yyyy-MM-dd HH:mm:ss")); // 获取启动图标 - Logger.info("定位启动图标"); - ViewRect launch = waitAndFindPic(of("启动图标").getFile(), 0.9, 10); + Logger.info("查找启动图标"); + ViewRect launch = findLegend("启动图标", 0.9); if (launch != null) { Logger.info("启动图标坐标:", launch.toString()); - Logger.info("启动程序"); + Logger.info("点击启动图标"); mouseLeftClick(launch); + Logger.info("等待程序启动中,请稍等..."); delay(10 * 1000); } - Logger.info("定位城镇"); -// -// delayUnstable(); -// new Task_离线收益(this, focusRect).run(); -// -// delayUnstable(); -// new Task_收留避难者(this, focusRect).run(); -// -// // 矿场攻击检测任务 -// delayUnstable(1000); -// new Task_探险领取(this, focusRect).run(); - Logger.info("启动循环任务"); while (JMainService.getInstance().run) { - new Task_返回城镇(this, focusRect).run(); + // 任意界面优先返回城镇 + new Task_定位城镇(this, focusRect).run(); - // 矿场攻击检测任务 - new Task_采矿被攻击(this, focusRect).run(); + // 可按优先级排序以下任务 + { + // 矿场攻击检测任务 + new Task_采矿被攻击(this, focusRect).run(); - // 避难者 - delayUnstable(1000); - new Task_收留避难者(this, focusRect).run(); + // 避难者 + new Task_收留避难者(this, focusRect).run(); - // 自动采矿任务 - delayUnstable(1000); - new Task_自动采矿(this, focusRect).run(); + // 自动采矿任务 + new Task_自动采矿(this, focusRect).run(); + } } } } diff --git a/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_返回城镇.java b/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_定位城镇.java similarity index 96% rename from src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_返回城镇.java rename to src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_定位城镇.java index 5b848b9..fa63149 100644 --- a/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_返回城镇.java +++ b/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_定位城镇.java @@ -4,9 +4,9 @@ import xyz.wbsite.jmacro.JMacro; import xyz.wbsite.jmacro.base.ViewRect; import xyz.wbsite.jmacro.util.Logger; -public class Task_返回城镇 extends BaseTask { +public class Task_定位城镇 extends BaseTask { - public Task_返回城镇(JMacro macro, ViewRect viewRect) { + public Task_定位城镇(JMacro macro, ViewRect viewRect) { super(macro, viewRect); } diff --git a/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_探险领取.java b/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_探险领取.java index 677f300..fa02269 100644 --- a/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_探险领取.java +++ b/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_探险领取.java @@ -28,7 +28,7 @@ public class Task_探险领取 extends BaseTask { } Logger.info("进入探险界面成功"); - ViewRect[] viewRects = macro.waitAndMatchLegend(new String[]{"探险_领取", "探险_不可领取"}, 5); + ViewRect[] viewRects = macro.waitAndMatchLegends(0.9, 5, "探险_领取", "探险_不可领取"); if (viewRects[0] != null) { // 可以领取 Logger.info("定位领取按钮"); ViewRect 探险_领取 = macro.waitAndMatchLegend("探险_领取", 0.8); diff --git a/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_收留避难者.java b/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_收留避难者.java index c859281..c7fc77d 100644 --- a/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_收留避难者.java +++ b/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_收留避难者.java @@ -12,7 +12,7 @@ public class Task_收留避难者 extends BaseTask { @Override public void task(JMacro macro, ViewRect viewRect) { - ViewRect rect = macro.waitAndMatchLegend("城镇_避难者", 0.9,3); + ViewRect rect = macro.matchLegend("城镇_避难者", 0.9); if (rect == null) { Logger.info("未发现避难者"); return; @@ -21,19 +21,15 @@ public class Task_收留避难者 extends BaseTask { Logger.info("收留避难者"); macro.mouseLeftClick(rect); - - macro.delayUnstable(); - ViewRect rect1 = macro.waitAndMatchLegend("城镇_欢迎新成员", 0.9); + ViewRect rect1 = macro.waitAndMatchLegend("城镇_欢迎新成员", 0.9, 2000); if (rect1 == null) { Logger.info("收留避难者异常"); return; } - macro.delayUnstable(); Logger.info("欢迎新成员"); macro.mouseLeftClick(rect1); - macro.delayUnstable(); Logger.info("返回城镇"); } } diff --git a/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_离线收益.java b/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_离线收益.java deleted file mode 100644 index 05bdd18..0000000 --- a/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_离线收益.java +++ /dev/null @@ -1,26 +0,0 @@ -package xyz.wbsite.jmacro.wjdr.task; - -import xyz.wbsite.jmacro.JMacro; -import xyz.wbsite.jmacro.base.ViewRect; -import xyz.wbsite.jmacro.util.Logger; - -public class Task_离线收益 extends BaseTask { - - public Task_离线收益(JMacro macro, ViewRect viewRect) { - super(macro, viewRect); - } - - @Override - public void task(JMacro macro, ViewRect viewRect) { - macro.delayUnstable(); - // 定位离线收益弹框,关闭弹框 - ViewRect rect = macro.matchLegend("城镇_离线收益", 0.9); - if (rect != null) { - macro.mouseLeftClick(rect); - Logger.info("检测到离线收益弹框,关闭弹框"); - } else { - Logger.info("未检测到离线收益弹框"); - } - macro.delayUnstable(); - } -} diff --git a/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_自动采矿.java b/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_自动采矿.java index c8ed328..d44d839 100644 --- a/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_自动采矿.java +++ b/src/main/java/xyz/wbsite/jmacro/wjdr/task/Task_自动采矿.java @@ -54,14 +54,14 @@ public class Task_自动采矿 extends BaseTask { }; for (String type : types) { Logger.info("搜索资源【{}】", type); - boolean collect = collect(type, 3); - if (collect) { // 中断采集 + boolean success = collect(type, 3); + if (!success) { // 中断采集 break; } } // 检测是否是搜索界面 - ViewRect 野外_任务2 = macro.waitAndMatchLegend("野外_任务", 9); + ViewRect 野外_任务2 = macro.matchLegend("野外_任务", 0.9); if (野外_任务2 != null) { Logger.info("退出资源搜索界面"); macro.mouseLeftClick(this.viewRect); @@ -69,11 +69,10 @@ public class Task_自动采矿 extends BaseTask { ViewRect 城1 = macro.waitAndMatchLegend("城镇", 0.9); if (城1 == null) { - Logger.error("未检测到【城镇】,采矿终止"); + Logger.error("未检测到【城镇】,异常终止"); return; } Logger.info("返回城镇"); - macro.delayUnstable(); } /** @@ -96,14 +95,12 @@ public class Task_自动采矿 extends BaseTask { if (clevel > level) { TaskUtil.execTask(() -> { Logger.info("调整等级"); - macro.delayUnstable(700); macro.mouseLeftClick(macro.of(51, 777)); }, clevel - level, 1000); } if (clevel < level) { TaskUtil.execTask(() -> { Logger.info("调整等级"); - macro.delayUnstable(700); macro.mouseLeftClick(macro.of(360, 777)); }, level - clevel, 1000); } @@ -115,18 +112,14 @@ public class Task_自动采矿 extends BaseTask { } Logger.info("点击搜索{}{}级矿", type, level); - macro.delayUnstable(); macro.mouseLeftClick(野外_资源搜索); - macro.delayUnstable(); - ViewRect 采集 = macro.waitAndMatchLegend("野外_资源采集", 0.98); + macro.delayUnstable(1500); + ViewRect 采集 = macro.waitAndMatchLegend("野外_资源采集", 0.9); if (采集 != null) { macro.mouseLeftClick(采集); - macro.delayUnstable(1000); - - ViewRect[] viewRects = macro.matchLegend("野外_资源出征", "野外_资源无对队列", "野外_资源无士兵"); - + ViewRect[] viewRects = macro.waitAndMatchLegends(0.9, "野外_资源出征", "野外_资源无对队列", "野外_资源无士兵"); if (viewRects[0] != null) { Logger.info("出征"); macro.mouseLeftClick(viewRects[0]); @@ -134,22 +127,15 @@ public class Task_自动采矿 extends BaseTask { } if (viewRects[1] != null) { Logger.info("队列已满,取消采集"); - macro.delayUnstable(1000); - macro.mouseLeftClick(macro.of(471, 250)); - - Logger.info("队列已满,取消采集"); - macro.delayUnstable(1000); macro.mouseLeftClick(macro.of(471, 250)); return false; } if (viewRects[2] != null) { Logger.info("士兵不足,取消采集"); - macro.delayUnstable(1000); - macro.mouseLeftClick(macro.of(32,30)); + macro.mouseLeftClick(macro.of(32, 30)); return false; } - - } else if (level > 1) { + } else if (level > 1) { // 当前等级无资源,降低资源等级 return collect(type, level - 1); }