diff --git a/pom.xml b/pom.xml index 33659e1a..8473f8a9 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ 4.0.0 bh.bot 99bot - 1.7.0 + 1.7.1 diff --git a/release.sh b/release.sh index 89edf1c7..0ac862c7 100755 --- a/release.sh +++ b/release.sh @@ -80,6 +80,7 @@ cat ./README.release.md >> ./release/README.md # Remove secret rm -f ./release/bh-client/*.html +rm -f ./release/readonly.*.properties # Compress output FILE=Bit-Heroes-99bot-Release-v$VERSION.zip diff --git a/src/main/java/bh/bot/Main.java b/src/main/java/bh/bot/Main.java index aa3fcfe5..344f7399 100644 --- a/src/main/java/bh/bot/Main.java +++ b/src/main/java/bh/bot/Main.java @@ -46,9 +46,11 @@ import bh.bot.common.Telegram; import bh.bot.common.exceptions.InvalidFlagException; import bh.bot.common.exceptions.NotImplementedException; +import bh.bot.common.types.Familiar; import bh.bot.common.types.ParseArgumentsResult; import bh.bot.common.types.ScreenResolutionProfile; import bh.bot.common.types.annotations.AppMeta; +import bh.bot.common.types.flags.FlagBribe; import bh.bot.common.types.flags.FlagCloseGameWindowAfterExit; import bh.bot.common.types.flags.FlagDoExpedition; import bh.bot.common.types.flags.FlagDoGauntlet; @@ -271,6 +273,7 @@ private static ParseArgumentsResult parseArguments(String[] args) throws Invalid // Parse param int exitAfter = 0; String cfgProfileName = null; + ArrayList familiarToBribeWithGems = null; for (FlagPattern flagPattern : usingFlagPatterns) { if (!flagPattern.isAllowParam()) continue; @@ -284,11 +287,19 @@ private static ParseArgumentsResult parseArguments(String[] args) throws Invalid cfgProfileName = ((FlagProfileName) flagPattern).parseParams().get(0); continue; } + + if (flagPattern instanceof FlagBribe) { + familiarToBribeWithGems = ((FlagBribe) flagPattern).parseParams(); + continue; + } throw new NotImplementedException( String.format("Not implemented extracting param for flag '--%s' (Class: %s)", flagPattern.getName(), flagPattern.getClass().getSimpleName())); } + + if (familiarToBribeWithGems == null) + familiarToBribeWithGems = new ArrayList<>(); info("Application will exit after %s", TimeUtil.niceTimeLong(exitAfter)); @@ -337,6 +348,7 @@ private static ParseArgumentsResult parseArguments(String[] args) throws Invalid li.disableTelegramNoti = usingFlagPatterns.stream().anyMatch(x -> x instanceof FlagMuteNoti); li.screenResolutionProfile = screenResolutionProfile; li.cfgProfileName = cfgProfileName; + li.familiarToBribeWithGems = familiarToBribeWithGems; // events li.ePvp = usingFlagPatterns.stream().anyMatch(x -> x instanceof FlagDoPvp); li.eWorldBoss = usingFlagPatterns.stream().anyMatch(x -> x instanceof FlagDoWorldBoss); diff --git a/src/main/java/bh/bot/app/AbstractApplication.java b/src/main/java/bh/bot/app/AbstractApplication.java index 58916892..88cdc75c 100644 --- a/src/main/java/bh/bot/app/AbstractApplication.java +++ b/src/main/java/bh/bot/app/AbstractApplication.java @@ -54,6 +54,7 @@ import bh.bot.common.jna.MiniClientMacOsJna; import bh.bot.common.jna.MiniClientWindowsJna; import bh.bot.common.jna.SteamWindowsJna; +import bh.bot.common.types.Familiar; import bh.bot.common.types.Offset; import bh.bot.common.types.ParseArgumentsResult; import bh.bot.common.types.ScreenResolutionProfile; @@ -71,6 +72,7 @@ import bh.bot.common.utils.ColorizeUtil; import bh.bot.common.utils.ImageUtil; import bh.bot.common.utils.InteractionUtil; +import bh.bot.common.utils.InteractionUtil.Keyboard; import bh.bot.common.utils.InteractionUtil.Screen.ScreenCapturedResult; import bh.bot.common.utils.RandomUtil; import bh.bot.common.utils.StringUtil; @@ -595,6 +597,7 @@ protected Tuple2 detectRadioButtons(Rectangle scanRect) { private static final int detectDcSleepSecs = 60; private static final int reactiveAutoSleepSecs = 10; private static final int closeEnterGameDialogNewsSleepSecs = 60; + private static final int persuadeSleepSecs = 60; protected void internalDoSmallTasks(AtomicBoolean masterSwitch, SmallTasks st) { try { @@ -603,6 +606,16 @@ protected void internalDoSmallTasks(AtomicBoolean masterSwitch, SmallTasks st) { long nextReactiveAuto = addSec(reactiveAutoSleepSecs); final AtomicInteger continousRed = new AtomicInteger(0); long nextCloseEnterGameDialogNews = addSec(closeEnterGameDialogNewsSleepSecs); + final AtomicInteger continousPersuadeScreen = new AtomicInteger(0); + long nextPersuade = addSec(persuadeSleepSecs); + + if (st.persuade) { + if (Configuration.enableDevFeatures && !argumentInfo.familiarToBribeWithGems.contains(Familiar.Kaleido)) + argumentInfo.familiarToBribeWithGems.add(Familiar.Kaleido); + for (Familiar f : argumentInfo.familiarToBribeWithGems) + warn("Will persuade %s with gems", f.name()); + } + while (!masterSwitch.get()) { sleep(1_000); @@ -620,6 +633,9 @@ protected void internalDoSmallTasks(AtomicBoolean masterSwitch, SmallTasks st) { if (st.closeEnterGameNewsDialog && nextCloseEnterGameDialogNews <= System.currentTimeMillis()) nextCloseEnterGameDialogNews = closeEnterGameDialogNews(); + + if (st.persuade && nextPersuade <= System.currentTimeMillis()) + nextPersuade = doPersuade(continousPersuadeScreen); } } catch (Exception ex) { ex.printStackTrace(); @@ -638,6 +654,7 @@ protected static class SmallTasks { public final boolean reactiveAuto; public final boolean autoExit; public final boolean closeEnterGameNewsDialog; + public final boolean persuade; private SmallTasks(Builder b) { this.clickTalk = b.f(0); @@ -645,6 +662,7 @@ private SmallTasks(Builder b) { this.reactiveAuto = b.f(2); this.autoExit = b.f(3); this.closeEnterGameNewsDialog = b.f(4); + this.persuade = b.f(5); } public static Builder builder() { @@ -686,7 +704,87 @@ public Builder autoExit() { public Builder closeEnterGameNewsDialog() { return this.set(4); } + + public Builder persuade() { + return this.set(5); + } + } + } + + private long doPersuade(AtomicInteger continousPersuadeScreen) { + Point pBribeButton = findImage(BwMatrixMeta.Metas.Globally.Buttons.persuadeBribe); + Point pPersuadeButton = pBribeButton != null ? null : findImage(BwMatrixMeta.Metas.Globally.Buttons.persuade); + if (pPersuadeButton != null || pBribeButton != null) { + int continous = continousPersuadeScreen.addAndGet(1); + if (continous > 0) { + if (continous % 10 == 1) + Telegram.sendMessage("Found persuade screen", true); + + if (persuade(BwMatrixMeta.Metas.Persuade.Labels.kaleido, Familiar.Kaleido, pPersuadeButton, pBribeButton)) { + // + } else { + persuade(true, pPersuadeButton, pBribeButton); + } + } else { + info("Found persuade screen"); + } + } else { + continousPersuadeScreen.set(0); + } + return addSec(persuadeSleepSecs); + } + + private boolean persuade(BwMatrixMeta im, Familiar familiar, Point pPersuadeButton, Point pBribeButton) { + String name = familiar.name().toUpperCase(); + + if (im.notAvailable) { + warn("Persuading %s has not yet been implemented for this profile", name); + return false; + } + + if (!argumentInfo.familiarToBribeWithGems.contains(familiar)) { + persuade(true, pPersuadeButton, pBribeButton); + info("Bribe %s with gold", name); + return true; } + + Point pFamiliar = findImage(im); + if (pFamiliar == null) + return false; + try { + persuade(false, pPersuadeButton, pBribeButton); + warn(name); + Telegram.sendMessage(name, false); + } catch (Exception e) { + e.printStackTrace(); + err(name); + Telegram.sendMessage(String.format("%s failure: %s", name, e.getMessage()), true); + } + return true; + } + + private void persuade(boolean gold, Point pPersuadeButton, Point pBribeButton) { + Point p = null; + if (gold) { + if (pPersuadeButton != null) { + p = pPersuadeButton; + } else if (pBribeButton != null) { + p = fromRelativeToAbsoluteBasedOnPreviousResult(BwMatrixMeta.Metas.Globally.Buttons.persuadeBribe, pBribeButton, Configuration.screenResolutionProfile.getOffsetButtonBribePersuade()); + } + } else { + if (pPersuadeButton != null) { + p = fromRelativeToAbsoluteBasedOnPreviousResult(BwMatrixMeta.Metas.Globally.Buttons.persuade, pPersuadeButton, Configuration.screenResolutionProfile.getOffsetButtonPersuade()); + } else if (pBribeButton != null) { + p = pBribeButton; + } + } + + if (p == null) + throw new InvalidDataException("Implemented wrongly"); + + mouseMoveAndClickAndHide(p); + sleep(5_000); + Keyboard.sendEnter(); } private long doClickTalk() { diff --git a/src/main/java/bh/bot/app/AfkApp.java b/src/main/java/bh/bot/app/AfkApp.java index ce3cca32..9e532dc8 100644 --- a/src/main/java/bh/bot/app/AfkApp.java +++ b/src/main/java/bh/bot/app/AfkApp.java @@ -121,6 +121,7 @@ protected void internalRun(String[] args) { .reactiveAuto() // .autoExit() // .closeEnterGameNewsDialog() // + .persuade() // .build() // ), // () -> doCheckGameScreenOffset(masterSwitch) // diff --git a/src/main/java/bh/bot/app/FishingApp.java b/src/main/java/bh/bot/app/FishingApp.java index b5ba6512..920bfddf 100644 --- a/src/main/java/bh/bot/app/FishingApp.java +++ b/src/main/java/bh/bot/app/FishingApp.java @@ -42,6 +42,12 @@ protected void internalRun(String[] args) { final int loop = arg; info("Loop: %d", loop); + try { + adjustScreenOffset(); + } catch (Exception ex) { + err("Unable to detect screen offset: %s", ex.getMessage()); + } + int retry = 5; Point labelFishingCord; while ((labelFishingCord = detectLabelFishing()) == null && retry-- > 0) { diff --git a/src/main/java/bh/bot/app/ReRunApp.java b/src/main/java/bh/bot/app/ReRunApp.java index 0ace1f10..0e9e1088 100644 --- a/src/main/java/bh/bot/app/ReRunApp.java +++ b/src/main/java/bh/bot/app/ReRunApp.java @@ -45,6 +45,7 @@ protected void internalRun(String[] args) { .clickDisconnect() // .reactiveAuto() // .autoExit() // + .persuade() // .build() // ), // () -> detectDefeatedOnRaid(masterSwitch), diff --git a/src/main/java/bh/bot/app/farming/AbstractDoFarmingApp.java b/src/main/java/bh/bot/app/farming/AbstractDoFarmingApp.java index f82203bc..baf58021 100644 --- a/src/main/java/bh/bot/app/farming/AbstractDoFarmingApp.java +++ b/src/main/java/bh/bot/app/farming/AbstractDoFarmingApp.java @@ -67,6 +67,7 @@ protected void internalRun(String[] args) { .reactiveAuto() // .autoExit() // .closeEnterGameNewsDialog() // + .persuade() // .build() // ), // () -> doCheckGameScreenOffset(masterSwitch) // diff --git a/src/main/java/bh/bot/common/types/Familiar.java b/src/main/java/bh/bot/common/types/Familiar.java new file mode 100644 index 00000000..6cb66f41 --- /dev/null +++ b/src/main/java/bh/bot/common/types/Familiar.java @@ -0,0 +1,5 @@ +package bh.bot.common.types; + +public enum Familiar { + Kaleido +} \ No newline at end of file diff --git a/src/main/java/bh/bot/common/types/ParseArgumentsResult.java b/src/main/java/bh/bot/common/types/ParseArgumentsResult.java index bd829d11..95e49a73 100644 --- a/src/main/java/bh/bot/common/types/ParseArgumentsResult.java +++ b/src/main/java/bh/bot/common/types/ParseArgumentsResult.java @@ -28,6 +28,7 @@ public class ParseArgumentsResult { public boolean eRaid; public ScreenResolutionProfile screenResolutionProfile; public String cfgProfileName; + public ArrayList familiarToBribeWithGems; @SuppressWarnings("rawtypes") public ParseArgumentsResult(Class applicationClass, String[] arguments, ArrayList usingFlags) { diff --git a/src/main/java/bh/bot/common/types/ScreenResolutionProfile.java b/src/main/java/bh/bot/common/types/ScreenResolutionProfile.java index c46bc046..e8b46948 100644 --- a/src/main/java/bh/bot/common/types/ScreenResolutionProfile.java +++ b/src/main/java/bh/bot/common/types/ScreenResolutionProfile.java @@ -193,6 +193,12 @@ public abstract class ScreenResolutionProfile { public abstract Offset getOffsetDialogNews(); + public abstract Offset getOffsetButtonPersuade(); + + public abstract Offset getOffsetButtonBribePersuade(); + + public abstract Offset getOffsetLabelPersuadeKaleido(); + public static class WebProfile extends ScreenResolutionProfile { @Override @@ -644,6 +650,22 @@ public Offset getOffsetButtonAcceptExpedition() { public Offset getOffsetDialogNews() { return new Offset(356, 77); } + + @Override + public Offset getOffsetButtonPersuade() { + return new Offset(139, 329); + } + + @Override + public Offset getOffsetButtonBribePersuade() { + return new Offset(567, 329); + } + + @Override + public Offset getOffsetLabelPersuadeKaleido() { + // TODO Auto-generated method stub + return null; + } } public static class SteamProfile extends ScreenResolutionProfile { @@ -1097,5 +1119,20 @@ public Offset getOffsetButtonAcceptExpedition() { public Offset getOffsetDialogNews() { return new Offset(359, 69); } + + @Override + public Offset getOffsetButtonPersuade() { + return new Offset(155, 305); + } + + @Override + public Offset getOffsetButtonBribePersuade() { + return new Offset(556, 305); + } + + @Override + public Offset getOffsetLabelPersuadeKaleido() { + return new Offset(202, 70); + } } } diff --git a/src/main/java/bh/bot/common/types/flags/FlagBribe.java b/src/main/java/bh/bot/common/types/flags/FlagBribe.java new file mode 100644 index 00000000..3f36c2c4 --- /dev/null +++ b/src/main/java/bh/bot/common/types/flags/FlagBribe.java @@ -0,0 +1,59 @@ +package bh.bot.common.types.flags; + +import bh.bot.app.AbstractApplication; +import bh.bot.app.AfkApp; +import bh.bot.app.ReRunApp; +import bh.bot.app.farming.AbstractDoFarmingApp; +import bh.bot.common.exceptions.InvalidFlagException; +import bh.bot.common.exceptions.NotSupportedException; +import bh.bot.common.types.Familiar; + +public class FlagBribe extends FlagPattern { + + @Override + protected Familiar internalParseParam(String paramPart) throws InvalidFlagException { + String[] spl = paramPart.toLowerCase().split("[\\,\\;]"); + for (String s : spl) { + switch (s) { + case "kaleido": + return Familiar.Kaleido; + default: + throw new NotSupportedException(String.format("Unknown value '%s' of flag %s", s, getCode())); + } + } + throw new InvalidFlagException(String.format("Passing invalid value for flag %s", getCode())); + } + + @Override + public boolean isAllowParam() { + return true; + } + + @Override + protected boolean isAllowMultiple() { + return true; + } + + @Override + public boolean isGlobalFlag() { + return false; + } + + @Override + public String getName() { + return "bribe"; + } + + @Override + public String getDescription() { + return "Auto bribe with gems"; + } + + @Override + protected boolean internalCheckIsSupportedByApp(AbstractApplication instance) { + return instance instanceof AfkApp + || instance instanceof ReRunApp + || instance instanceof AbstractDoFarmingApp; + } + +} diff --git a/src/main/java/bh/bot/common/types/flags/FlagPattern.java b/src/main/java/bh/bot/common/types/flags/FlagPattern.java index b18b0f7f..5449304e 100644 --- a/src/main/java/bh/bot/common/types/flags/FlagPattern.java +++ b/src/main/java/bh/bot/common/types/flags/FlagPattern.java @@ -20,9 +20,8 @@ public final void pushRaw(String raw) { public final ArrayList parseParams() throws InvalidFlagException { ArrayList result = new ArrayList<>(); - for (String rawFlag : rawFlags) { + for (String rawFlag : rawFlags) result.add(parseParam(rawFlag)); - } return result; } @@ -30,6 +29,12 @@ public final T parseParam(String raw) throws InvalidFlagException { if (!isAllowParam()) throw new NotSupportedException(String.format("Flag '%s' does not support parameter", getCode())); + if (isAllowEmptyParam() && !raw.contains("=")) { + if (!raw.equals(getCode())) + throw new InvalidFlagException("Invalid flag header (passing wrong flag?)"); + return getDefaultValueWhenEmptyParam(); + } + if (!raw.contains("=")) throw new InvalidFlagException(String.format("Flag '%s=?' expected parameter but doesn't contains parameter", getCode())); @@ -67,8 +72,8 @@ protected boolean internalCheckIsSupportedByApp(AbstractApplication instance) { public final boolean isThisFlag(String raw) throws InvalidFlagException { String prefix = String.format("--%s", getName()); if (raw.equals(prefix)) { - if (isAllowParam()) - throw new InvalidFlagException(String.format("Flag '%s' is invalid, must contains parameter", raw)); + if (isAllowParam() && !isAllowEmptyParam()) + throw new InvalidFlagException(String.format("Flag '%s' is invalid, must contains parameter or have to allow empty param", raw)); countMatch++; if (countMatch > 1 && !isAllowMultiple()) throw new NotSupportedException(String.format("Flag '--%s' can not be declared multiple times", getName())); @@ -88,6 +93,14 @@ public final boolean isThisFlag(String raw) throws InvalidFlagException { public boolean isAllowParam() { return false; } + + public boolean isAllowEmptyParam() { + return false; + } + + public T getDefaultValueWhenEmptyParam() { + throw new NotImplementedException(); + } @SuppressWarnings("BooleanMethodIsAlwaysInverted") protected boolean isAllowMultiple() { diff --git a/src/main/java/bh/bot/common/types/flags/Flags.java b/src/main/java/bh/bot/common/types/flags/Flags.java index 362fc57a..9a1e3b04 100644 --- a/src/main/java/bh/bot/common/types/flags/Flags.java +++ b/src/main/java/bh/bot/common/types/flags/Flags.java @@ -22,5 +22,6 @@ public class Flags { new FlagProfileName(), new FlagExitAfkAfterIfWaitResourceGeneration(), new FlagCloseGameWindowAfterExit(), + new FlagBribe(), }; } diff --git a/src/main/java/bh/bot/common/types/images/BwMatrixMeta.java b/src/main/java/bh/bot/common/types/images/BwMatrixMeta.java index bc14eb99..00bba616 100644 --- a/src/main/java/bh/bot/common/types/images/BwMatrixMeta.java +++ b/src/main/java/bh/bot/common/types/images/BwMatrixMeta.java @@ -32,7 +32,7 @@ public class BwMatrixMeta { private final int[] lastMatch = new int[]{-1, -1}; private final byte tolerant; private final String imageNameCode; - private final boolean notAvailable; + public final boolean notAvailable; private final Short[][] originalTpPixelPart; public BwMatrixMeta(BufferedImageInfo mxBii, Offset coordinateOffset, int blackPixelRgb, BufferedImage tpBi) { @@ -209,6 +209,8 @@ public static class Buttons { public static BwMatrixMeta radioButton; public static BwMatrixMeta close; public static BwMatrixMeta mapButtonOnFamiliarUi; + public static BwMatrixMeta persuade; + public static BwMatrixMeta persuadeBribe; } public static class Dialogs { @@ -220,6 +222,12 @@ public static class Dialogs { } } + public static class Persuade { + public static class Labels { + public static BwMatrixMeta kaleido; + } + } + public static class Dungeons { public static class Buttons { public static BwMatrixMeta rerun; @@ -381,6 +389,16 @@ public static void load() throws IOException { Configuration.screenResolutionProfile.getOffsetButtonMapOnFamiliarUi(), // 0x000000 ); + Metas.Globally.Buttons.persuade = BwMatrixMeta.from(// + "buttons/globally.persuade?", + Configuration.screenResolutionProfile.getOffsetButtonPersuade(), // + 0xFFFFFF + ); + Metas.Globally.Buttons.persuadeBribe = BwMatrixMeta.from(// + "buttons/globally.persuade-bribe?", + Configuration.screenResolutionProfile.getOffsetButtonBribePersuade(), // + 0xFFFFFF + ); Metas.Globally.Dialogs.confirmQuitBattle = BwMatrixMeta.from(// "dialogs/globally.confirm-quit-battle?", Configuration.screenResolutionProfile.getOffsetDialogConfirmQuitBattle(), // @@ -410,7 +428,14 @@ public static void load() throws IOException { "buttons/dungeons.rerun?", Configuration.screenResolutionProfile.getOffsetButtonDungeonReRun(), // 0xFFFFFF); - + + // Persuade + Metas.Persuade.Labels.kaleido = BwMatrixMeta.from(// + "labels/persuade.kaleido?", + Configuration.screenResolutionProfile.getOffsetLabelPersuadeKaleido(), // + 0xFFFF00 + ); + // Fishing Metas.Fishing.Labels.fishing = BwMatrixMeta.from(// "labels/fishing?", diff --git a/src/main/java/bh/bot/common/utils/ImageUtil.java b/src/main/java/bh/bot/common/utils/ImageUtil.java index cc26e6d2..7b1bf04b 100644 --- a/src/main/java/bh/bot/common/utils/ImageUtil.java +++ b/src/main/java/bh/bot/common/utils/ImageUtil.java @@ -13,6 +13,8 @@ import java.util.ArrayList; import java.util.List; +import static bh.bot.common.Log.err; + public class ImageUtil { public static BufferedImageInfo loadMxImageFromResource(String path) throws IOException { if (!path.toLowerCase().trim().endsWith("-mx.bmp")) @@ -125,7 +127,12 @@ public static TestTransformMxResult testTransformMx(BufferedImage bi, int rgb, i tp = new BufferedImage(mx.getWidth(), mx.getHeight(), mx.getType()); for (int y = 0; y < tp.getHeight(); y++) for (int x = 0; x < tp.getWidth(); x++) - tp.setRGB(x, y, bi.getRGB(x + minX, y + minY)); + try { + tp.setRGB(x, y, bi.getRGB(x + minX, y + minY)); + } catch (ArrayIndexOutOfBoundsException ex) { + err("Problem while moving pixel from bi %d,%d to tp %d,%d (minX = %d, minY = %d)", x, y, x + minX, y + minY, minX, minY); + throw ex; + } return new TestTransformMxResult(bi, mx, tp, new Offset(minX, minY)); } finally { diff --git a/src/main/java/bh/bot/common/utils/ThreadUtil.java b/src/main/java/bh/bot/common/utils/ThreadUtil.java index e137d658..7d591511 100644 --- a/src/main/java/bh/bot/common/utils/ThreadUtil.java +++ b/src/main/java/bh/bot/common/utils/ThreadUtil.java @@ -1,6 +1,10 @@ package bh.bot.common.utils; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; @@ -10,22 +14,29 @@ import static bh.bot.common.Log.*; public class ThreadUtil { - public static void waitDone(Runnable... runAbles) { - ExecutorService pool = Executors.newFixedThreadPool(runAbles.length); - List> completableFutures = Arrays.stream(runAbles).map(x -> CompletableFuture.runAsync(x, pool)).collect(Collectors.toList()); - while (!completableFutures.stream().allMatch(CompletableFuture::isDone)) { - sleep(3000); - } - info("waitDone finished"); - debug("ExecutorService is shutting down now"); - pool.shutdownNow(); - } + public static void waitDone(Runnable... runAbles) { + ExecutorService pool = Executors.newFixedThreadPool(runAbles.length); + List> completableFutures = Arrays.stream(runAbles) + .map(x -> CompletableFuture.runAsync(x, pool)).collect(Collectors.toList()); + while (!completableFutures.stream().allMatch(CompletableFuture::isDone)) { + sleep(3000); + } + + String pattern = "HH:mm"; + DateFormat df = new SimpleDateFormat(pattern); + Date today = Calendar.getInstance().getTime(); + String now = df.format(today); - public static void sleep(int ms) { - try { - Thread.sleep(Math.max(10, ms)); - } catch (InterruptedException ex) { - err("Failure to sleep"); - } - } + info("waitDone finished at %s", now); + debug("ExecutorService is shutting down now"); + pool.shutdownNow(); + } + + public static void sleep(int ms) { + try { + Thread.sleep(Math.max(10, ms)); + } catch (InterruptedException ex) { + err("Failure to sleep"); + } + } } diff --git a/src/main/java/bh/bot/common/utils/VersionUtil.java b/src/main/java/bh/bot/common/utils/VersionUtil.java index 1ad0f3cd..fc92c48b 100644 --- a/src/main/java/bh/bot/common/utils/VersionUtil.java +++ b/src/main/java/bh/bot/common/utils/VersionUtil.java @@ -1,8 +1,9 @@ package bh.bot.common.utils; import static bh.bot.common.Log.debug; +import static bh.bot.common.Log.dev; +import static bh.bot.common.Log.info; import static bh.bot.common.Log.isOnDebugMode; -import static bh.bot.common.Log.warn; import java.io.BufferedReader; import java.io.InputStreamReader; @@ -34,7 +35,7 @@ public static boolean checkForLatestVersion() { int responseCode = httpURLConnection.getResponseCode(); if (responseCode != 200 && responseCode != 304) { - debug("VersionUtil::checkForLatestVersion response code %d", responseCode); + dev("VersionUtil::checkForLatestVersion response code %d", responseCode); return false; } @@ -59,15 +60,20 @@ public static boolean checkForLatestVersion() { String tagName = obj.getString("tag_name"); if (tagName == null || !tagName.startsWith("release-")) continue; - + SematicVersion sematicVersion = new SematicVersion(tagName.substring(8)); int compare = appVer.compareTo(sematicVersion); - + if (compare < 0) { - warn( // - "%s has new update v%s, please go to download new version at https://github.com/9-9-9-9/Bit-Heroes-bot/releases", // - Main.botName, sematicVersion.toString() // + String msg = String.format( // + "** NEW UPDATE AVAILABLE ** %s v%s is now available at https://github.com/9-9-9-9/Bit-Heroes-bot/releases", // + Main.botName, // + sematicVersion.toString() // ); + info(ColorizeUtil.formatAsk, msg); + info(ColorizeUtil.formatError, msg); + info(ColorizeUtil.formatWarning, msg); + info(ColorizeUtil.formatInfo, msg); return true; } } diff --git a/src/main/resources/game-images/steam/buttons/globally.persuade-bribe-tp.bmp b/src/main/resources/game-images/steam/buttons/globally.persuade-bribe-tp.bmp new file mode 100644 index 00000000..5066f267 Binary files /dev/null and b/src/main/resources/game-images/steam/buttons/globally.persuade-bribe-tp.bmp differ diff --git a/src/main/resources/game-images/steam/buttons/globally.persuade-tp.bmp b/src/main/resources/game-images/steam/buttons/globally.persuade-tp.bmp new file mode 100644 index 00000000..2c5d05cc Binary files /dev/null and b/src/main/resources/game-images/steam/buttons/globally.persuade-tp.bmp differ diff --git a/src/main/resources/game-images/steam/labels/persuade.kaleido-tp.bmp b/src/main/resources/game-images/steam/labels/persuade.kaleido-tp.bmp new file mode 100644 index 00000000..b41dbbed Binary files /dev/null and b/src/main/resources/game-images/steam/labels/persuade.kaleido-tp.bmp differ diff --git a/src/main/resources/game-images/web/buttons/globally.persuade-bribe-tp.bmp b/src/main/resources/game-images/web/buttons/globally.persuade-bribe-tp.bmp new file mode 100644 index 00000000..fb92958e Binary files /dev/null and b/src/main/resources/game-images/web/buttons/globally.persuade-bribe-tp.bmp differ diff --git a/src/main/resources/game-images/web/buttons/globally.persuade-tp.bmp b/src/main/resources/game-images/web/buttons/globally.persuade-tp.bmp new file mode 100644 index 00000000..98e20582 Binary files /dev/null and b/src/main/resources/game-images/web/buttons/globally.persuade-tp.bmp differ