def run(self): """ Starts the fishing code explained in comments in detail """ fishing_event.init() self.fishPixWindow = WindowClient(color=cv2.COLOR_RGB2HSV) # check for game window and stuff self.gui.bot_started(True) 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() 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]) logging.info("Fishing engine stopped") self.gui.bot_started(False) fishing_event.unsubscribe() self.fishPixWindow.destory()
def _crash_safe(self): logging.debug(f"starting {self.name} engine thread") self.window = WindowClient(color=cv2.COLOR_RGB2GRAY, show_name=f"{self.name} debug") self.gui.bot_started(True) try: self.run() except Exception: logging.error(f"Unhandled exception occurred while running {self.name} engine") print_exc() self.state = 0 self.gui.bot_started(False) self.window.destroy() logging.debug(f"{self.name} engine thread safely exiting")
def run(self): addons_req = [libgps, lam2, fishyqr] for addon in addons_req: if not helper.addon_exists(*addon): helper.install_addon(*addon) FullAuto.state = State.NONE self.gui.bot_started(True) self.window = WindowClient(color=cv2.COLOR_RGB2GRAY, show_name="Full auto debug") try: self.window.crop = get_qr_location(self.window.get_capture()) if self.window.crop is None: logging.warning("FishyQR not found") self.start = False raise Exception("FishyQR not found") if not self.calibrator.all_callibrated(): logging.error("you need to calibrate first") self.fisher.toggle_start() fishing_event.unsubscribe() self.controls.initialize() while self.start and WindowClient.running(): if self.show_crop: self.window.show(self.show_crop, func=image_pre_process) else: time.sleep(0.1) except: traceback.print_exc() if self.window.get_capture() is None: logging.error("Game window not found") self.gui.bot_started(False) self.controls.unassign_keys() self.window.show(False) logging.info("Quitting") self.window.destory() self.fisher.toggle_start()
def run(self): self.show_crop = False FullAuto.state = State.NONE self.gui.bot_started(True) fishing_event.unsubscribe() self.fisher.toggle_start() self.window = WindowClient(color=cv2.COLOR_RGB2GRAY, show_name="Full auto debug") try: if self.calibrate.crop is None: self.calibrate.update_crop(enable_crop=False) self.window.crop = self.calibrate.crop if not is_tesseract_installed(): logging.info("tesseract not found") downlaoad_and_extract_tesseract() if not self.calibrate.all_callibrated(): logging.error("you need to callibrate first") self.controls.initialize() while self.start and WindowClient.running(): self.window.show(self.show_crop, func=image_pre_process) if not self.show_crop: time.sleep(0.1) except: traceback.print_exc() if self.window.get_capture() is None: logging.error("Game window not found") self.gui.bot_started(False) self.controls.unassign_keys() self.window.show(False) logging.info("Quitting") self.window.destory() self.fisher.toggle_start()
def get_values(window: WindowClient): values = None for _ in range(5): img = window.processed_image(func=_image_pre_process) if img is None: logging.debug("Couldn't capture window.") continue if not window.crop: window.crop = _get_qr_location(img) if not window.crop: logging.debug("FishyQR not found.") continue img = window.processed_image(func=_image_pre_process) values = _get_values_from_image(img) if not values: window.crop = None logging.debug("Values not able to read.") continue break return values
def _engine_loop(self): skip_count = 0 while self.state == 1 and WindowClient.running(): # crop qr and get the values from it self.values = qr_detection.get_values(self.window) # if fishyqr fails to get read multiple times, stop the bot if not self.values: if skip_count >= 5: logging.error( "Couldn't read values from FishyQR, Stopping engine..." ) return skip_count += 1 time.sleep(0.1) else: skip_count = 0 if self.values: fishing_mode.loop(self.values[3]) self.first_loop_done = True time.sleep(0.1)
class SemiFisherEngine(IEngine): def __init__(self, gui_ref: Optional['Callable[[], GUI]']): super().__init__(gui_ref) self.fishPixWindow = None def run(self): """ Starts the fishing code explained in comments in detail """ fishing_event.init() self.fishPixWindow = WindowClient(color=cv2.COLOR_RGB2HSV) # check for game window and stuff self.gui.bot_started(True) 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() 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]) logging.info("Fishing engine stopped") self.gui.bot_started(False) fishing_event.unsubscribe() self.fishPixWindow.destory() def _wait_and_check(self): time.sleep(10) if not FishEvent.FishingStarted and self.start: logging.warning( "Doesn't look like fishing has started \nCheck out #read-me-first on our discord channel to troubleshoot the issue" ) def show_pixel_vals(self): def show(): freq = 0.5 t = 0 while t < 10.0: t += freq logging.debug( str(FishingMode.CurrentMode) + ":" + str(self.fishPixWindow.get_capture()[0][0])) time.sleep(freq) logging.debug("Will display pixel values for 10 seconds") time.sleep(5) Thread(target=show, args=()).start() def toggle_start(self): self.start = not self.start if self.start: self.thread = Thread(target=self.run) self.thread.start()
def func(): while self.start and WindowClient.running(): self.window.show(self.show_crop)
class FullAuto(IEngine): rotate_by = 30 state = State.NONE def __init__(self, gui_ref): from fishy.engine.fullautofisher.controls import Controls from fishy.engine.fullautofisher import controls from fishy.engine.fullautofisher.calibrate import Calibrate from fishy.engine.fullautofisher.test import Test super().__init__(gui_ref) self._hole_found_flag = False self._curr_rotate_y = 0 self.fisher = SemiFisherEngine(None) self.calibrate = Calibrate(self) self.test = Test(self) self.controls = Controls(controls.get_controls(self)) self.show_crop = False def run(self): self.show_crop = False FullAuto.state = State.NONE self.gui.bot_started(True) fishing_event.unsubscribe() self.fisher.toggle_start() self.window = WindowClient(color=cv2.COLOR_RGB2GRAY, show_name="Full auto debug") try: if self.calibrate.crop is None: self.calibrate.update_crop(enable_crop=False) self.window.crop = self.calibrate.crop if not is_tesseract_installed(): logging.info("tesseract not found") downlaoad_and_extract_tesseract() if not self.calibrate.all_callibrated(): logging.error("you need to callibrate first") self.controls.initialize() while self.start and WindowClient.running(): self.window.show(self.show_crop, func=image_pre_process) if not self.show_crop: time.sleep(0.1) except: traceback.print_exc() if self.window.get_capture() is None: logging.error("Game window not found") self.gui.bot_started(False) self.controls.unassign_keys() self.window.show(False) logging.info("Quitting") self.window.destory() self.fisher.toggle_start() def get_coods(self): img = self.window.processed_image(func=image_pre_process) return get_values_from_image(img) def move_to(self, target): if target is None: logging.error("set target first") return if not self.calibrate.all_callibrated(): logging.error("you need to callibrate first") return current = self.get_coods() print(f"Moving from {(current[0], current[1])} to {target}") move_vec = target[0] - current[0], target[1] - current[1] dist = math.sqrt(move_vec[0] ** 2 + move_vec[1] ** 2) print(f"distance: {dist}") if dist < 5e-05: print("distance very small skipping") return target_angle = math.degrees(math.atan2(-move_vec[1], move_vec[0])) + 90 from_angle = current[2] self.rotate_to(target_angle, from_angle) walking_time = dist / self.calibrate.move_factor print(f"walking for {walking_time}") kb.press('w') time.sleep(walking_time) kb.release('w') print("done") def rotate_to(self, target_angle, from_angle=None): if from_angle is None: _, _, from_angle = self.get_coods() if target_angle < 0: target_angle = 360 + target_angle while target_angle > 360: target_angle -= 360 print(f"Rotating from {from_angle} to {target_angle}") angle_diff = target_angle - from_angle if abs(angle_diff) > 180: angle_diff = (360 - abs(angle_diff)) * sign(angle_diff) * -1 rotate_times = int(angle_diff / self.calibrate.rot_factor) * -1 print(f"rotate_times: {rotate_times}") for _ in range(abs(rotate_times)): mse.move(sign(rotate_times) * FullAuto.rotate_by * -1, 0) time.sleep(0.05) def look_for_hole(self): self._hole_found_flag = False if FishingMode.CurrentMode == fishing_mode.State.LOOK: return True def found_hole(e): if e == fishing_mode.State.LOOK: self._hole_found_flag = True fishing_mode.subscribers.append(found_hole) t = 0 while not self._hole_found_flag and t <= self.calibrate.time_to_reach_bottom / 3: mse.move(0, FullAuto.rotate_by) time.sleep(0.05) t += 0.05 while not self._hole_found_flag and t > 0: mse.move(0, -FullAuto.rotate_by) time.sleep(0.05) t -= 0.05 self._curr_rotate_y = t fishing_mode.subscribers.remove(found_hole) return self._hole_found_flag def rotate_back(self): while self._curr_rotate_y > 0.01: mse.move(0, -FullAuto.rotate_by) time.sleep(0.05) self._curr_rotate_y -= 0.05 def toggle_start(self): if self.start and FullAuto.state != State.NONE: logging.info("Please turn off RECORDING/PLAYING first") return self.start = not self.start if self.start: self.thread = Thread(target=self.run) self.thread.start()
class IEngine: def __init__(self, gui_ref: 'Callable[[], GUI]'): self.get_gui = gui_ref # 0 - off, 1 - running, 2 - quitting self.state = 0 self.window = None self.thread = None self.name = "default" @property def gui(self): if self.get_gui is None: return GUIFuncsMock() return self.get_gui().funcs @property def start(self): return self.state == 1 def toggle_start(self): if self.state == 0: self.turn_on() else: self.turn_off() def turn_on(self): self.state = 1 self.thread = Thread(target=self._crash_safe) self.thread.start() def join(self): if self.thread: logging.debug(f"waiting for {self.name} engine") self.thread.join() def turn_off(self): """ this method only signals the thread to close using start flag, its the responsibility of the thread to shut turn itself off """ if self.state == 1: logging.debug(f"sending turn off signal to {self.name} engine") self.state = 2 else: logging.debug(f"{self.name} engine already signaled to turn off ") # todo: implement force turn off on repeated calls # noinspection PyBroadException def _crash_safe(self): logging.debug(f"starting {self.name} engine thread") self.window = WindowClient(color=cv2.COLOR_RGB2GRAY, show_name=f"{self.name} debug") self.gui.bot_started(True) try: self.run() except Exception: logging.error(f"Unhandled exception occurred while running {self.name} engine") print_exc() self.state = 0 self.gui.bot_started(False) self.window.destroy() logging.debug(f"{self.name} engine thread safely exiting") def run(self): raise NotImplementedError