mirror of
https://github.com/fishyboteso/fishyboteso.git
synced 2024-08-30 18:32:13 +00:00
Merge pull request #97 from fishyboteso/improvement/fishyqr-integration
This commit is contained in:
commit
bde31fce85
@ -1,2 +1,4 @@
|
||||
from fishy import constants
|
||||
|
||||
from fishy.__main__ import main
|
||||
__version__ = "0.5.2"
|
||||
__version__ = constants.version
|
||||
|
@ -9,13 +9,14 @@ import win32gui
|
||||
|
||||
import fishy
|
||||
from fishy import gui, helper, web
|
||||
from fishy.constants import chalutier, lam2
|
||||
from fishy.constants import chalutier, lam2, fishyqr, libgps
|
||||
from fishy.engine.common.event_handler import EngineEventHandler
|
||||
from fishy.gui import GUI, splash, update_dialog
|
||||
from fishy.helper import hotkey
|
||||
from fishy.helper.active_poll import active
|
||||
from fishy.helper.config import config
|
||||
from fishy.helper.hotkey.hotkey_process import hotkey
|
||||
from fishy.helper.migration import Migration
|
||||
|
||||
|
||||
def check_window_name(title):
|
||||
@ -28,6 +29,8 @@ def check_window_name(title):
|
||||
|
||||
# noinspection PyBroadException
|
||||
def initialize(window_to_hide):
|
||||
Migration.migrate()
|
||||
|
||||
helper.create_shortcut_first()
|
||||
helper.initialize_uid()
|
||||
|
||||
@ -62,10 +65,7 @@ def initialize(window_to_hide):
|
||||
helper.install_thread_excepthook()
|
||||
sys.excepthook = helper.unhandled_exception_logging
|
||||
|
||||
if not config.get("addoninstalled", 0) or helper.get_addonversion(chalutier[0]) < chalutier[2]:
|
||||
helper.install_addon(*chalutier)
|
||||
helper.install_addon(*lam2)
|
||||
config.set("addoninstalled", helper.get_addonversion(chalutier[0]))
|
||||
helper.install_required_addons()
|
||||
|
||||
|
||||
def main():
|
||||
|
@ -1,6 +1,11 @@
|
||||
apiversion = 2
|
||||
chalutier = ("Chalutier", "https://www.esoui.com/downloads/dl2934/Chalutier_1.1.4.zip", 114)
|
||||
lam2 = ("LibAddonMenu-2.0", "https://www.esoui.com/downloads/dl7/LibAddonMenu-2.0r32.zip", 32)
|
||||
|
||||
fishyqr = ("FishyQR", "https://github.com/fishyboteso/FishyQR/files/6329586/FishyQR.zip", 100)
|
||||
# removed since 0.5.3
|
||||
chalutier = ("Chalutier", "https://www.esoui.com/downloads/dl2934/Chalutier_1.1.4.zip", 114)
|
||||
|
||||
# addons used
|
||||
lam2 = ("LibAddonMenu-2.0", "https://www.esoui.com/downloads/dl7/LibAddonMenu-2.0r32.zip", 32)
|
||||
fishyqr = ("FishyQR", "https://github.com/fishyboteso/FishyQR/files/7575974/FishyQR.zip", 101)
|
||||
libgps = ("LibGPS", "https://cdn.esoui.com/downloads/file601/LibGPS_3_0_3.zip", 30)
|
||||
|
||||
version = "0.5.3"
|
||||
|
@ -9,6 +9,15 @@ from pyzbar.pyzbar import decode, ZBarSymbol
|
||||
from fishy.helper.helper import get_documents
|
||||
|
||||
|
||||
def image_pre_process(img):
|
||||
scale_percent = 100 # percent of original size
|
||||
width = int(img.shape[1] * scale_percent / 100)
|
||||
height = int(img.shape[0] * scale_percent / 100)
|
||||
dim = (width, height)
|
||||
img = cv2.resize(img, dim, interpolation=cv2.INTER_AREA)
|
||||
return img
|
||||
|
||||
|
||||
def get_qr_location(og_img):
|
||||
"""
|
||||
code from https://stackoverflow.com/a/45770227/4512396
|
||||
@ -41,7 +50,7 @@ def get_values_from_image(img):
|
||||
try:
|
||||
for qr in decode(img, symbols=[ZBarSymbol.QRCODE]):
|
||||
vals = qr.data.decode('utf-8').split(",")
|
||||
return float(vals[0]), float(vals[1]), float(vals[2])
|
||||
return tuple(float(v) for v in vals)
|
||||
|
||||
logging.error("FishyQR not found")
|
||||
return None
|
@ -1,5 +1,6 @@
|
||||
import logging
|
||||
import math
|
||||
import traceback
|
||||
from enum import Enum
|
||||
from threading import Thread
|
||||
|
||||
@ -75,10 +76,15 @@ def loop_end():
|
||||
cv2.waitKey(25)
|
||||
|
||||
|
||||
# noinspection PyBroadException
|
||||
def run():
|
||||
# todo use config
|
||||
while WindowServer.status == Status.RUNNING:
|
||||
loop()
|
||||
try:
|
||||
loop()
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
WindowServer.status = Status.CRASHED
|
||||
loop_end()
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
import math
|
||||
import logging
|
||||
import math
|
||||
import time
|
||||
@ -16,8 +15,8 @@ from fishy.engine.fullautofisher.mode.calibrator import Calibrator
|
||||
from fishy.engine.fullautofisher.mode.imode import FullAutoMode
|
||||
from fishy.engine.fullautofisher.mode.player import Player
|
||||
from fishy.engine.fullautofisher.mode.recorder import Recorder
|
||||
from fishy.engine.fullautofisher.qr_detection import (get_qr_location,
|
||||
get_values_from_image)
|
||||
from fishy.engine.common.qr_detection import (get_qr_location,
|
||||
get_values_from_image, image_pre_process)
|
||||
from fishy.engine.semifisher import fishing_event, fishing_mode
|
||||
from fishy.engine.semifisher.fishing_mode import FishingMode
|
||||
from fishy.helper import helper, hotkey
|
||||
@ -29,15 +28,6 @@ mse = mouse.Controller()
|
||||
kb = keyboard.Controller()
|
||||
|
||||
|
||||
def image_pre_process(img):
|
||||
scale_percent = 100 # percent of original size
|
||||
width = int(img.shape[1] * scale_percent / 100)
|
||||
height = int(img.shape[0] * scale_percent / 100)
|
||||
dim = (width, height)
|
||||
img = cv2.resize(img, dim, interpolation=cv2.INTER_AREA)
|
||||
return img
|
||||
|
||||
|
||||
class FullAuto(IEngine):
|
||||
rotate_by = 30
|
||||
|
||||
@ -56,12 +46,6 @@ class FullAuto(IEngine):
|
||||
self.mode = None
|
||||
|
||||
def run(self):
|
||||
|
||||
addons_req = [libgps, lam2, fishyqr]
|
||||
for addon in addons_req:
|
||||
if not helper.addon_exists(*addon):
|
||||
helper.install_addon(*addon)
|
||||
|
||||
self.gui.bot_started(True)
|
||||
self.window = WindowClient(color=cv2.COLOR_RGB2GRAY, show_name="Full auto debug")
|
||||
|
||||
|
@ -4,14 +4,16 @@ import typing
|
||||
from threading import Thread
|
||||
from typing import Callable, Optional
|
||||
|
||||
import cv2
|
||||
|
||||
from fishy.helper.helper import log_raise
|
||||
from playsound import playsound
|
||||
|
||||
from fishy.engine.common.IEngine import IEngine
|
||||
from fishy.engine.common.qr_detection import get_qr_location, get_values_from_image, image_pre_process
|
||||
from fishy.engine.common.window import WindowClient
|
||||
from fishy.engine.semifisher import fishing_event, fishing_mode
|
||||
from fishy.engine.semifisher.fishing_event import FishEvent
|
||||
from fishy.engine.semifisher.fishing_mode import Colors, FishingMode
|
||||
from fishy.engine.semifisher.pixel_loc import PixelLoc
|
||||
from fishy.helper import helper
|
||||
from fishy.helper.luaparser import sv_color_extract
|
||||
|
||||
@ -22,7 +24,7 @@ if typing.TYPE_CHECKING:
|
||||
class SemiFisherEngine(IEngine):
|
||||
def __init__(self, gui_ref: Optional['Callable[[], GUI]']):
|
||||
super().__init__(gui_ref)
|
||||
self.fishPixWindow = None
|
||||
self.window = None
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
@ -30,34 +32,43 @@ class SemiFisherEngine(IEngine):
|
||||
code explained in comments in detail
|
||||
"""
|
||||
fishing_event.init()
|
||||
self.fishPixWindow = WindowClient()
|
||||
self.window = WindowClient(color=cv2.COLOR_RGB2GRAY, show_name="semifisher debug")
|
||||
|
||||
# check for game window and stuff
|
||||
self.gui.bot_started(True)
|
||||
|
||||
sv_color_extract(Colors)
|
||||
|
||||
if self.get_gui:
|
||||
logging.info("Starting the bot engine, look at the fishing hole to start fishing")
|
||||
Thread(target=self._wait_and_check).start()
|
||||
|
||||
while self.start and WindowClient.running():
|
||||
capture = self.fishPixWindow.get_capture()
|
||||
self.window.crop = get_qr_location(self.window.get_capture())
|
||||
if self.window.crop is None:
|
||||
log_raise("FishyQR not found")
|
||||
|
||||
while self.start and WindowClient.running():
|
||||
capture = self.window.processed_image(func=image_pre_process)
|
||||
|
||||
# if window server crashed
|
||||
if capture is None:
|
||||
# if window server crashed
|
||||
self.gui.bot_started(False)
|
||||
self.toggle_start()
|
||||
continue
|
||||
|
||||
self.fishPixWindow.crop = PixelLoc.val
|
||||
fishing_mode.loop(capture[0][0])
|
||||
# crop qr and get the values from it
|
||||
values = get_values_from_image(capture)
|
||||
if values is None:
|
||||
self.gui.bot_started(False)
|
||||
self.toggle_start()
|
||||
continue
|
||||
|
||||
fishing_mode.loop(values[3])
|
||||
time.sleep(0.1)
|
||||
|
||||
self.window.show(False)
|
||||
logging.info("Fishing engine stopped")
|
||||
self.gui.bot_started(False)
|
||||
fishing_event.unsubscribe()
|
||||
self.fishPixWindow.destory()
|
||||
self.window.destory()
|
||||
|
||||
def _wait_and_check(self):
|
||||
time.sleep(10)
|
||||
@ -71,7 +82,7 @@ class SemiFisherEngine(IEngine):
|
||||
t = 0
|
||||
while t < 10.0:
|
||||
t += freq
|
||||
logging.debug(str(FishingMode.CurrentMode) + ":" + str(self.fishPixWindow.get_capture()[0][0]))
|
||||
logging.debug(str(FishingMode.CurrentMode) + ":" + str(self.window.get_capture()[0][0]))
|
||||
time.sleep(freq)
|
||||
|
||||
logging.debug("Will display pixel values for 10 seconds")
|
||||
|
@ -107,7 +107,10 @@ def fisher_callback(event: State):
|
||||
|
||||
|
||||
def on_idle():
|
||||
if FishEvent.previousState in (State.FISHING, State.REELIN):
|
||||
if FishEvent.previousState == State.REELIN:
|
||||
logging.info("HOLE DEPLETED")
|
||||
_sound_and_send_fishy_data()
|
||||
elif FishEvent.previousState == State.FISHING:
|
||||
logging.info("FISHING INTERRUPTED")
|
||||
_sound_and_send_fishy_data()
|
||||
|
||||
|
@ -17,21 +17,6 @@ class State(Enum):
|
||||
DEAD = 15
|
||||
|
||||
|
||||
Colors = {
|
||||
State.IDLE : [255, 255, 255],
|
||||
State.LOOKAWAY : [ 76, 0, 76],
|
||||
State.LOOKING : [101, 69, 0],
|
||||
State.DEPLETED : [ 0, 76, 76],
|
||||
State.NOBAIT : [255, 204, 0],
|
||||
State.FISHING : [ 75, 156, 213],
|
||||
State.REELIN : [ 0, 204, 0],
|
||||
State.LOOT : [ 0, 0, 204],
|
||||
State.INVFULL : [ 0, 0, 51],
|
||||
State.FIGHT : [204, 0, 0],
|
||||
State.DEAD : [ 51, 51, 51]
|
||||
}
|
||||
|
||||
|
||||
def _notify(event):
|
||||
for subscriber in subscribers:
|
||||
subscriber(event)
|
||||
@ -42,17 +27,12 @@ class FishingMode:
|
||||
PrevMode = State.IDLE
|
||||
|
||||
|
||||
def loop(rgb):
|
||||
def loop(state_num: int):
|
||||
"""
|
||||
Executed in the start of the main loop in fishy.py
|
||||
Changes modes, calls mode events (callbacks) when mode is changed
|
||||
|
||||
:param rgb: rgb read by the bot
|
||||
"""
|
||||
FishingMode.CurrentMode = State.IDLE
|
||||
for s in State:
|
||||
if all(rgb == Colors[s]):
|
||||
FishingMode.CurrentMode = s
|
||||
FishingMode.CurrentMode = State(state_num)
|
||||
|
||||
if FishingMode.CurrentMode != FishingMode.PrevMode:
|
||||
_notify(FishingMode.CurrentMode)
|
||||
|
@ -1,66 +0,0 @@
|
||||
import cv2
|
||||
|
||||
|
||||
def get_keypoint_from_image(img):
|
||||
"""
|
||||
convert image int hsv
|
||||
creates a mask for brown color
|
||||
uses blob detection to find a blob in the mask
|
||||
filter the blobs to find the correct one
|
||||
|
||||
:param img: rgb image
|
||||
:return: location of the pixel which is used to detect different fishing states
|
||||
"""
|
||||
|
||||
# Setup SimpleBlobDetector parameters.
|
||||
hsv_img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
|
||||
lower = (99, 254, 100)
|
||||
upper = (100, 255, 101)
|
||||
mask = cv2.inRange(hsv_img, lower, upper)
|
||||
|
||||
# Setup SimpleBlobDetector parameters.
|
||||
params = cv2.SimpleBlobDetector_Params()
|
||||
|
||||
# Change thresholds
|
||||
params.minThreshold = 10
|
||||
params.maxThreshold = 255
|
||||
|
||||
params.filterByColor = True
|
||||
params.blobColor = 255
|
||||
|
||||
params.filterByCircularity = False
|
||||
params.filterByConvexity = False
|
||||
params.filterByInertia = False
|
||||
|
||||
params.filterByArea = True
|
||||
params.minArea = 10.0
|
||||
|
||||
detector = cv2.SimpleBlobDetector_create(params)
|
||||
|
||||
# Detect blobs.
|
||||
key_points = detector.detect(mask)
|
||||
|
||||
if len(key_points) <= 0:
|
||||
return None
|
||||
|
||||
return int(key_points[0].pt[0]), int(key_points[0].pt[1])
|
||||
|
||||
|
||||
class PixelLoc:
|
||||
"""
|
||||
finds the pixel loc and store it
|
||||
"""
|
||||
|
||||
val = None
|
||||
|
||||
@staticmethod
|
||||
def config():
|
||||
"""
|
||||
Uses the game window to get an image of the game screen
|
||||
then uses `GetKeypointFromImage()` to find the Chalutier pixel location
|
||||
:return: false if pixel loc not found
|
||||
"""
|
||||
|
||||
PixelLoc.val = (0, 0, 1, 1)
|
||||
|
||||
return True
|
@ -9,7 +9,7 @@ from ttkthemes import ThemedTk
|
||||
from fishy import helper
|
||||
from fishy.web import web
|
||||
|
||||
from ..constants import chalutier, lam2
|
||||
from ..constants import chalutier, lam2, fishyqr
|
||||
from ..helper.config import config
|
||||
from .discord_login import discord_login
|
||||
from ..helper.hotkey.hotkey_process import hotkey
|
||||
@ -59,15 +59,13 @@ def _create(gui: 'GUI'):
|
||||
filemenu.add_command(label="Update", command=helper.update)
|
||||
|
||||
def installer():
|
||||
if filemenu.entrycget(4, 'label') == "Remove Chalutier":
|
||||
if helper.remove_addon(chalutier[0]) == 0:
|
||||
filemenu.entryconfigure(4, label="Install Chalutier")
|
||||
if filemenu.entrycget(4, 'label') == "Remove FishyQR":
|
||||
if helper.remove_addon(fishyqr[0]) == 0:
|
||||
filemenu.entryconfigure(4, label="Install FishyQR")
|
||||
else:
|
||||
r = helper.install_addon(*chalutier)
|
||||
r += helper.install_addon(*lam2)
|
||||
if r == 0:
|
||||
filemenu.entryconfigure(4, label="Remove Chalutier")
|
||||
chaEntry = "Remove Chalutier" if helper.addon_exists(chalutier[0]) else "Install Chalutier"
|
||||
helper.install_required_addons(True)
|
||||
filemenu.entryconfigure(4, label="Remove FishyQR")
|
||||
chaEntry = "Remove FishyQR" if helper.addon_exists(fishyqr[0]) else "Install FishyQR"
|
||||
filemenu.add_command(label=chaEntry, command=installer)
|
||||
menubar.add_cascade(label="Options", menu=filemenu)
|
||||
|
||||
|
@ -5,5 +5,5 @@ from .helper import (addon_exists, create_shortcut, create_shortcut_first,
|
||||
install_addon, install_thread_excepthook, manifest_file,
|
||||
not_implemented, open_web, playsound_multiple,
|
||||
remove_addon, restart, unhandled_exception_logging,
|
||||
update)
|
||||
update, install_required_addons)
|
||||
from .luaparser import sv_color_extract
|
||||
|
@ -22,6 +22,8 @@ from win32gui import GetForegroundWindow, GetWindowText
|
||||
|
||||
import fishy
|
||||
from fishy import web
|
||||
from fishy.constants import libgps, lam2, fishyqr
|
||||
from fishy.helper.config import config
|
||||
|
||||
|
||||
def playsound_multiple(path, count=2):
|
||||
@ -190,17 +192,34 @@ def get_addonversion(name, url=None, v=None):
|
||||
return 0
|
||||
|
||||
|
||||
def install_required_addons(force=False):
|
||||
addons_req = [libgps, lam2, fishyqr]
|
||||
addon_version = config.get("addon_version", {})
|
||||
installed = False
|
||||
for addon in addons_req:
|
||||
if force or (addon_exists(*addon) and
|
||||
(addon[0] not in addon_version or (
|
||||
addon[0] in addon_version and addon_version[addon[0]] < addon[2]))):
|
||||
remove_addon(*addon)
|
||||
install_addon(*addon)
|
||||
addon_version[addon[0]] = addon[2]
|
||||
installed = True
|
||||
config.set("addon_version", addon_version)
|
||||
if installed:
|
||||
logging.info("Please make sure to enable \"Allow outdated addons\" in ESO")
|
||||
|
||||
|
||||
# noinspection PyBroadException
|
||||
def install_addon(name, url, v=None):
|
||||
try:
|
||||
r = requests.get(url, stream=True)
|
||||
z = ZipFile(BytesIO(r.content))
|
||||
z.extractall(path=get_addondir())
|
||||
logging.info("Add-On " + name +
|
||||
" installed successfully!\nPlease make sure to enable \"Allow outdated addons\" in ESO")
|
||||
logging.info("Add-On " + name + " installed successfully!")
|
||||
return 0
|
||||
except Exception:
|
||||
logging.error("Could not install Add-On " + name + ", try doing it manually")
|
||||
traceback.print_exc()
|
||||
return 1
|
||||
|
||||
|
||||
|
33
fishy/helper/migration.py
Normal file
33
fishy/helper/migration.py
Normal file
@ -0,0 +1,33 @@
|
||||
import logging
|
||||
|
||||
from fishy.helper.auto_update import _normalize_version
|
||||
|
||||
from fishy.constants import chalutier, version
|
||||
from fishy.helper import helper
|
||||
from .config import config
|
||||
|
||||
|
||||
class Migration:
|
||||
@staticmethod
|
||||
def up_to_0_5_3():
|
||||
helper.remove_addon(*chalutier)
|
||||
config.delete("addoninstalled")
|
||||
|
||||
@staticmethod
|
||||
def migrate():
|
||||
prev_version = _normalize_version(config.get("prev_version", "0.0.0"))
|
||||
current_version = _normalize_version(version)
|
||||
|
||||
if current_version > prev_version:
|
||||
for v, f in migration_code:
|
||||
if prev_version < _normalize_version(v) <= current_version:
|
||||
logging.info(f"running migration for {v}")
|
||||
f()
|
||||
config.set("prev_version", version)
|
||||
|
||||
|
||||
|
||||
migration_code = [
|
||||
# version, upgrade_code
|
||||
("0.5.3", Migration.up_to_0_5_3)
|
||||
]
|
Loading…
Reference in New Issue
Block a user