From b29fe87b899fe323a67659ee16c923fcd88738c9 Mon Sep 17 00:00:00 2001
From: HungPV <49741222+9-9-9-9@users.noreply.github.com>
Date: Mon, 20 Sep 2021 23:52:54 +0700
Subject: [PATCH] 1.7.1 fix bug (#39)
* now flag allow passing empty param
* warning when persuade screen appears
* auto bribe (persuade) kaleido
* temp dev feature
* change format notice when new update available
* fix bug detect screen steam
Co-authored-by: 9-9-9-9 <9-9-9-9>
---
pom.xml | 2 +-
release.sh | 1 +
src/main/java/bh/bot/Main.java | 12 +++
.../java/bh/bot/app/AbstractApplication.java | 98 ++++++++++++++++++
src/main/java/bh/bot/app/AfkApp.java | 1 +
src/main/java/bh/bot/app/FishingApp.java | 6 ++
src/main/java/bh/bot/app/ReRunApp.java | 1 +
.../bot/app/farming/AbstractDoFarmingApp.java | 1 +
.../java/bh/bot/common/types/Familiar.java | 5 +
.../common/types/ParseArgumentsResult.java | 1 +
.../common/types/ScreenResolutionProfile.java | 37 +++++++
.../bh/bot/common/types/flags/FlagBribe.java | 59 +++++++++++
.../bot/common/types/flags/FlagPattern.java | 21 +++-
.../java/bh/bot/common/types/flags/Flags.java | 1 +
.../bot/common/types/images/BwMatrixMeta.java | 29 +++++-
.../java/bh/bot/common/utils/ImageUtil.java | 9 +-
.../java/bh/bot/common/utils/ThreadUtil.java | 45 +++++---
.../java/bh/bot/common/utils/VersionUtil.java | 20 ++--
.../buttons/globally.persuade-bribe-tp.bmp | Bin 0 -> 2814 bytes
.../steam/buttons/globally.persuade-tp.bmp | Bin 0 -> 4758 bytes
.../steam/labels/persuade.kaleido-tp.bmp | Bin 0 -> 3806 bytes
.../buttons/globally.persuade-bribe-tp.bmp | Bin 0 -> 3190 bytes
.../web/buttons/globally.persuade-tp.bmp | Bin 0 -> 5814 bytes
23 files changed, 317 insertions(+), 32 deletions(-)
create mode 100644 src/main/java/bh/bot/common/types/Familiar.java
create mode 100644 src/main/java/bh/bot/common/types/flags/FlagBribe.java
create mode 100644 src/main/resources/game-images/steam/buttons/globally.persuade-bribe-tp.bmp
create mode 100644 src/main/resources/game-images/steam/buttons/globally.persuade-tp.bmp
create mode 100644 src/main/resources/game-images/steam/labels/persuade.kaleido-tp.bmp
create mode 100644 src/main/resources/game-images/web/buttons/globally.persuade-bribe-tp.bmp
create mode 100644 src/main/resources/game-images/web/buttons/globally.persuade-tp.bmp
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 0000000000000000000000000000000000000000..5066f267364f5a4654800b3c06ab11a511d256f4
GIT binary patch
literal 2814
zcmcJR&5Ke|7{+berfv6%UJM893$2OyfNW7ClAntpilAMf;Kn~-hzQz@xbdTfAsIt^
zcOnF$AmSi(2E|()?tyY_@pB!ml+967%60KLO
zRZJ1VV32L;^Z95IS!_`zve_&=vqI0FXrJ34Fpb4xG8>!rdOgkW^#N|vJg6|Z$=m64
zW@R{TTCdmZADqNlO(P%`qcy3mmck+74
z9gRlmaWT5xZkDOST`U%v4PwiFFzro*fEhX>(x96{qnd)
zNq><0c>Lq*W^SP9_V225Q&+Y;-+T*sy-mLrxD$y4`osb|#^dooAmI1=sf+BKbh}+<
zgD98FJ8|dpc|LtO98$U>H}AAsty-hO^7-w(FYlK9zQBD#&$H`2i07w7jQ`<2NhXu0
zT(Dno^&UjOIpgWB{Vo&=e7btSc_*)z{brytvC1tou<2!=Z&nCGjT`r%*X#9oJoK|d
zBXBzTeA3NklfES<4khz!`F_Hulg57++hkR2;0A{%>2ADusynnmV5-R7Xf(*FHSIwt
ba<|*<)$+8mcpsE>`a_HU;R7nP;l1h)X!%N1
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..2c5d05cca59a8cd790d19bc56de3ef5263f0738c
GIT binary patch
literal 4758
zcmdT|OG_J36t;h$i>^9}uOwPRYYTF8tK9Z)QB4wg(3t>sVMlO
z3!zAh8x=Q#MktC_tmvXp1Vt2lR8(-`LKh;m-{hFn+nGBv(YonnGC6bZcfWJ*mvbKz
zU$FODQmka-?#3sK&sBV`BwfcnDXIFbKK5{S`xP%OEiH(8!nC!uaa~zincc2LUZtR_yStnHKA+EKQ}Xii*rPXkdwb8K3SScw6ME$K
z_O=~i;-$8>mN89DO>jpV)ggq#VfNS6)e(GSV}qR<1F_#O&(oqQQ)ejNox=YfIVz>K-94OHafCE#eX_dV8VQPBm3PfiLAxN#f&%7Ge6r_
zQLL(zh@Lc-MDzqFm@V}zDJdaNy64`rkpkT9ot>SZe-~QGy*U`N+KBTLO&B;kJBun%
z(H8cuS>1O;JqfwHyUT%~l}e{5S#HJWvAGkI{#?-nZPwqo^k%
z*$4yzpam>BHsN6-SGiU+rl+UJ#>TK#PzQMZr1_qolNPE{dCc=uBou8UJ;4cP%ls6n
zVtU%9K4(J#(XX+wJ|7(&H8wWVa4t(va2_5W@_Fgt-~b*?XnNF~m;Nt3hlhs;;$?7f
zkO!#O6WdB0IMCnU54Dk>^Ft37hI91!$w(NZqoYjAda@@Pjf!B{l$p&h-KBnY_qmv!
zLqkJM3!B6JV}3Fx49d^w$NNx#`NjPRvDmNIQ?tKg*1B)lGhOQC%T2?;#rcl&Jf%18
zSP7X{uV-IhA0tHrw0CZ*+nhwt$_)6;=R55JM3~5agmBJu>-|WxzoQ8$zypMy(3y&*
zo^hb|o4PIP84Ly)WT_`3H3rdMSWjlN)RU1|jocUok*(95tO*{_~56>T9br#xaAy_E3SNIF@QV4>Dh4>eUT3FeL
zC|DebiiJO_h^3X4hF5m@yqPbeaSa3FOFPQfBrP`B{VgKPG}>8gWzU$brsjw==ARGagP#Z
znyxoBIq&Y!@7vnq0*p6M{Hv=ZA{$y)7h`5;6
z4RvG$!wlUVNL+;&@7>vfNC&x)1yBgi%>|a0$p6u(Dziv3`AeGFkNX
zS-bN4l>BdIfePx-5VEMax+2Zu26_E!Yk}ou|N1(4)Uh$Gvoqe-#pG0Z$=K|p4<+C;L>L#oJ!H-A>ob6EWG>s6dCL8cHZ8aOQw}ujpt`z
z!RHHyO=mI--UXfVeNo6lYi~E;UdV}vEsJRIxP?VdGT+c6aR$)ATb2cXGIuqUWno6b
zyc!$Jun12~=&h{~$HhG%7K@84Jg29=%}uHV(Y!ll7CO^iO59OZP+dU~7g>0BcS$oi
zJIjamtM~{D$Kb0S7Vro}+F_w9Q3LM&@+`*3K@nb^?&Gtuu%N|Tj1ny3&O#8tMPebU
z!EO3cSg5HKXQ4!OZ}>m5NUD+QfC4oU;|I#lzDR^45NT&$B%-l|Zew4lqobh63!Eso
zV%ZnY`+IjLLzUj=Kkf@xHcOhgFFphd&)J#hUXQ)H36vof8oJUXHXV!{3CH2FoteSQvIkf$MRG1r3p
zqBM&VvN(iI7UF!+t~@*habi(oAos-u^jcZqVw9N~l13KjXZ7_(^LgL)HU`*d0XK-A
X2wm({?sGeY^3k)?did6kxV&EszSbQ
zfCCNZ^?GSUs$Po&aa~?s?!rLSWOJ1_yXxG378mKF(mb+l^8Bzf9q$;qXfpo)Z*4m*ieM`iLAv80p1gk!Ej^
zgWdyM^!va~q$CmvjN<(M#@qO);cy9uDsdS6@NDq?q$!7ujSZv+2c8EjJ3Bk&
zaygw&Q_LVAP!$)9kx))fPS6S=u<89E_GO(sa6V8KAyWk+cTjiefM=N}qy!miA;GxnW5FWw75Kj;6`_D&|SC0V$
q2Zj|21y~?>d$Z9{!Q0#Zuy5dXaOm^Pfn=yJ=0~rstt~?^8Kpm+WkW*%
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..98e20582a89892adf5d6cacfdf99fd7c7d0c42a3
GIT binary patch
literal 5814
zcmdUzOH3qH6oyMzPGDpdp{YS;cxD(tn+|rP(A@&l(*rSNW(;afjM^cFfQE$|jR|1_
z1jdk{J6*8A6(NQV0s#^eB$3C02tzQD_nXA<3=5u#{?&&*xl^w$2R7bRSD!lfzvtfi
z>eQ`URaDv=D+P-S`*i%i!tWY>&q;CEOVXqB`ryI&?(a~ksi~1=x#4qZs$FM$R4I8~
z*W%-4yWPILyc}wz^Iut6i8v_Z#haU(B_$=$W5ABg7#PFD!zA0-*zoy$@X$!g
z%gecWdwV|5)6>v6vSRMKBLWYl!Z)K*l59yyN%QmbS}}XT`kzoS;oQ}t
z@S);#Iu8#ILydI)Mb2EU;>>=LGdr~gai#%WzkWUvT=D(=eXSTC;(V?Pa%P!|Gy6r(
z?9>{>nIgxBMv{?{0i;?ndn|JP`CEl^adGj|($dPx3OCm^OgJM45C{3p4J~qp9{tYD
z%*5l4lI6m}LS(YZNKl0m2m}ZS@|k;3k}Lj%bDXnZ>&EMsssB2Tw>y!1PXfUCt8|6D(F4TFxo~4nHWd#2F8rcM2k~
zeet1`n;ngYx}5pE=H}*b_Yr50Q)#R18Xk+B@8n&j2o^b0Ulutda#nimGjMj=qtO;NT#}Q|yhrAH4dQpP3RKK%&;+a9{!O>yPIP6`VC1ikwM|E;s^mn@$#c
zzx&1a?mZ8qy1H5nOExz#$!EVi^3w;(LnJI`F+MVogPY{@*X7ddx5INjIXMx7d%a$a
z=a=skCL(9CY}@^SNzkC2|(^WY^Wzabz~YS*s)u
zAdAmImeIW7_u2wwQHT?kGdENjCY-;ikY3A(3!BfXfW*1y2L*^ZXH1O02MckyT+ZNw
z*sZOt6ddbk9FC5TszytPxMX}SU|_w$vi}|D-Q8V)<-#X|6_hS#R^qiKY(BFX#?H55Ej|Z7c{kF^yn)$1F)@*YV=!5_Wnv=E8}vSiT9nMp%&?qEsk={jRe4hq=Vw~i
zk=P1n-LUMu2xodvp->h%lNbOmWnI_T*ViQ!&Mw`2#_PPGeaft;sGxy~oJB=%Z!ZVe
zoj3aX`$fHIYu{5s^Rv}_7Nhm_^zcY@=Z%4Z0a1??1?hFy&-kt)ibY$@XYNsDV4+Lg
z@EklkI#ShY4|U%MwKDSPayAm1t?RtefwC(YXV`heD7Y?XBQd^=@%!N3-ky<+{pOsp
zuFDP<;+&S2hNFUl0*l{~sBL$5H+Lr*O-)T=aC{WPp~<=qZJ(Jlb=29}DGq?`mX;QA
zB=}y(Rayhzk#cf!peH7{zhLL*=Ue}dq>V}I=j22=JIhvj=jD`SB{qOyJ)jk{hw?e&
zmYkBTtPM;!qZXRNw_<$m7!sRv#=?f@jnmUp>M=BL80Iq`VHDhiGmQkN2_r0LXl~w6
Yo^hqVmu{uX_