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 extends AbstractApplication> 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