mirror of
https://github.com/fishyboteso/fishyboteso.git
synced 2024-08-30 18:32:13 +00:00
refactored semifisher state machine feature to be much simpler,
- now different systems can subscribe to semifisher events
This commit is contained in:
parent
315adf9799
commit
c63ff4c3ba
@ -10,7 +10,7 @@ import pytesseract
|
|||||||
|
|
||||||
from fishy.engine import SemiFisherEngine
|
from fishy.engine import SemiFisherEngine
|
||||||
from fishy.engine.common.window import WindowClient
|
from fishy.engine.common.window import WindowClient
|
||||||
from fishy.engine.semifisher import fishing_event
|
from fishy.engine.semifisher import fishing_event, fishing_mode
|
||||||
|
|
||||||
from fishy.engine.common.IEngine import IEngine
|
from fishy.engine.common.IEngine import IEngine
|
||||||
from pynput import keyboard, mouse
|
from pynput import keyboard, mouse
|
||||||
@ -171,7 +171,7 @@ class FullAuto(IEngine):
|
|||||||
if e == "look":
|
if e == "look":
|
||||||
self._hole_found_flag = True
|
self._hole_found_flag = True
|
||||||
|
|
||||||
fishing_event.subscribers.append(found_hole)
|
fishing_mode.subscribers.append(found_hole)
|
||||||
|
|
||||||
t = 0
|
t = 0
|
||||||
while not self._hole_found_flag and t <= self.factors[2] / 2:
|
while not self._hole_found_flag and t <= self.factors[2] / 2:
|
||||||
@ -184,7 +184,7 @@ class FullAuto(IEngine):
|
|||||||
t -= 0.05
|
t -= 0.05
|
||||||
|
|
||||||
self._curr_rotate_y = t
|
self._curr_rotate_y = t
|
||||||
fishing_event.subscribers.remove(found_hole)
|
fishing_mode.subscribers.remove(found_hole)
|
||||||
return self._hole_found_flag
|
return self._hole_found_flag
|
||||||
|
|
||||||
def set_target(self):
|
def set_target(self):
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
import time
|
import time
|
||||||
import typing
|
import typing
|
||||||
from collections import Callable
|
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import pywintypes
|
from fishy.engine.semifisher.fishing_event import FishEvent
|
||||||
|
|
||||||
|
from fishy.engine.common.window import WindowClient
|
||||||
|
from fishy.engine.semifisher.fishing_mode import FishingMode
|
||||||
|
|
||||||
from fishy.engine.common.IEngine import IEngine
|
from fishy.engine.common.IEngine import IEngine
|
||||||
from fishy.engine.semifisher import fishing_event
|
from fishy.engine.semifisher import fishing_mode, fishing_event
|
||||||
from .fishing_event import HookEvent, StickEvent, LookEvent, IdleEvent
|
from fishy.engine.semifisher.pixel_loc import PixelLoc
|
||||||
from .fishing_mode import FishingMode
|
|
||||||
from .pixel_loc import PixelLoc
|
|
||||||
from ..common.window import WindowClient
|
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
if typing.TYPE_CHECKING:
|
||||||
from fishy.gui import GUI
|
from fishy.gui import GUI
|
||||||
@ -29,15 +29,7 @@ class SemiFisherEngine(IEngine):
|
|||||||
Starts the fishing
|
Starts the fishing
|
||||||
code explained in comments in detail
|
code explained in comments in detail
|
||||||
"""
|
"""
|
||||||
|
fishing_event.init()
|
||||||
action_key = self.config.get("action_key", "e")
|
|
||||||
|
|
||||||
# initializes fishing modes and their callbacks
|
|
||||||
FishingMode("hook", 0, HookEvent(action_key, False))
|
|
||||||
FishingMode("stick", 1, StickEvent())
|
|
||||||
FishingMode("look", 2, LookEvent(action_key))
|
|
||||||
FishingMode("idle", 3, IdleEvent(self.config.get("uid"), self.config.get("sound_notification")))
|
|
||||||
|
|
||||||
self.fishPixWindow = WindowClient(color=cv2.COLOR_RGB2HSV)
|
self.fishPixWindow = WindowClient(color=cv2.COLOR_RGB2HSV)
|
||||||
|
|
||||||
# check for game window and stuff
|
# check for game window and stuff
|
||||||
@ -55,13 +47,15 @@ class SemiFisherEngine(IEngine):
|
|||||||
|
|
||||||
self.fishPixWindow.crop = PixelLoc.val
|
self.fishPixWindow.crop = PixelLoc.val
|
||||||
hue_value = capture[0][0][0]
|
hue_value = capture[0][0][0]
|
||||||
FishingMode.loop(hue_value)
|
fishing_mode.loop(hue_value)
|
||||||
|
|
||||||
logging.info("Fishing engine stopped")
|
logging.info("Fishing engine stopped")
|
||||||
self.gui.bot_started(False)
|
self.gui.bot_started(False)
|
||||||
|
fishing_event.destroy()
|
||||||
|
|
||||||
def _wait_and_check(self):
|
def _wait_and_check(self):
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
if not fishing_event._FishingStarted and self.start:
|
if not FishEvent.FishingStarted and self.start:
|
||||||
self.gui.show_error("Doesn't look like fishing has started\n\n"
|
self.gui.show_error("Doesn't look like fishing has started\n\n"
|
||||||
"Check out #read-me-first on our discord channel to troubleshoot the issue")
|
"Check out #read-me-first on our discord channel to troubleshoot the issue")
|
||||||
|
|
||||||
@ -79,4 +73,9 @@ class SemiFisherEngine(IEngine):
|
|||||||
Thread(target=show, args=()).start()
|
Thread(target=show, args=()).start()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
logging.getLogger("").setLevel(logging.DEBUG)
|
||||||
|
# noinspection PyTypeChecker
|
||||||
|
fisher = SemiFisherEngine(None, None)
|
||||||
|
fisher.toggle_start()
|
||||||
|
|
||||||
|
@ -5,153 +5,93 @@ also implements callbacks which is called when states are changed
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from abc import abstractmethod, ABC
|
|
||||||
|
|
||||||
|
from fishy.engine.semifisher import fishing_mode
|
||||||
from playsound import playsound
|
from playsound import playsound
|
||||||
|
|
||||||
from fishy import web
|
from fishy import web
|
||||||
|
from fishy.engine.semifisher.fishing_mode import State
|
||||||
from fishy.helper import helper
|
from fishy.helper import helper
|
||||||
import keyboard
|
import keyboard
|
||||||
|
|
||||||
_fishCaught = 0
|
|
||||||
_totalFishCaught = 0
|
|
||||||
_stickInitTime = 0
|
|
||||||
_fish_times = []
|
|
||||||
_hole_start_time = 0
|
|
||||||
_FishingStarted = False
|
|
||||||
|
|
||||||
subscribers = []
|
class FishEvent:
|
||||||
|
fishCaught = 0
|
||||||
|
totalFishCaught = 0
|
||||||
|
stickInitTime = 0
|
||||||
|
fish_times = []
|
||||||
|
hole_start_time = 0
|
||||||
|
FishingStarted = False
|
||||||
|
previousState = State.IDLE
|
||||||
|
|
||||||
|
# initialize these
|
||||||
|
action_key = 'e'
|
||||||
|
collect_r = False
|
||||||
|
uid = None
|
||||||
|
sound = False
|
||||||
|
|
||||||
|
|
||||||
def _notify(event):
|
def init():
|
||||||
for subscriber in subscribers:
|
# todo load config
|
||||||
subscriber(event)
|
fishing_mode.subscribers.append(fisher_callback)
|
||||||
|
|
||||||
|
|
||||||
class FishEvent(ABC):
|
def destroy():
|
||||||
@abstractmethod
|
fishing_mode.subscribers.remove(fisher_callback)
|
||||||
def on_enter_callback(self, previous_mode):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def on_exit_callback(self, current_mode):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class HookEvent(FishEvent):
|
def fisher_callback(event: State):
|
||||||
|
callbacks_map = {State.HOOK: on_hook, State.LOOK: on_look, State.IDLE: on_idle, State.STICK: on_stick}
|
||||||
|
callbacks_map[event]()
|
||||||
|
FishEvent.previousState = event
|
||||||
|
|
||||||
def __init__(self, action_key: str, collect_r: bool):
|
|
||||||
self.action_key = action_key
|
|
||||||
self.collect_r = collect_r
|
|
||||||
|
|
||||||
def on_enter_callback(self, previous_mode):
|
def on_hook():
|
||||||
"""
|
"""
|
||||||
called when the fish hook is detected
|
called when the fish hook is detected
|
||||||
increases the `fishCaught` and `totalFishCaught`, calculates the time it took to catch
|
increases the `fishCaught` and `totalFishCaught`, calculates the time it took to catch
|
||||||
presses e to catch the fish
|
presses e to catch the fish
|
||||||
|
|
||||||
:param previous_mode: previous mode in the state machine
|
|
||||||
"""
|
"""
|
||||||
global _fishCaught, _totalFishCaught
|
FishEvent.fishCaught += 1
|
||||||
|
FishEvent.totalFishCaught += 1
|
||||||
|
time_to_hook = time.time() - FishEvent.stickInitTime
|
||||||
|
FishEvent.fish_times.append(time_to_hook)
|
||||||
|
logging.info("HOOOOOOOOOOOOOOOOOOOOOOOK....... " + str(FishEvent.fishCaught) + " caught " + "in " + str(
|
||||||
|
round(time_to_hook, 2)) + " secs. " + "Total: " + str(FishEvent.totalFishCaught))
|
||||||
|
|
||||||
_fishCaught += 1
|
keyboard.press_and_release(FishEvent.action_key)
|
||||||
_totalFishCaught += 1
|
|
||||||
time_to_hook = time.time() - _stickInitTime
|
|
||||||
_fish_times.append(time_to_hook)
|
|
||||||
logging.info("HOOOOOOOOOOOOOOOOOOOOOOOK....... " + str(_fishCaught) + " caught " + "in " + str(
|
|
||||||
round(time_to_hook, 2)) + " secs. " + "Total: " + str(_totalFishCaught))
|
|
||||||
# pyautogui.press(self.action_key)
|
|
||||||
keyboard.press_and_release(self.action_key)
|
|
||||||
|
|
||||||
if self.collect_r:
|
if FishEvent.collect_r:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
keyboard.press_and_release('r')
|
keyboard.press_and_release('r')
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
_notify("hook")
|
|
||||||
|
|
||||||
|
def on_look():
|
||||||
|
|
||||||
def on_exit_callback(self, current_mode):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class LookEvent(FishEvent):
|
|
||||||
"""
|
|
||||||
state when looking on a fishing hole
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, action_key: str):
|
|
||||||
self.action_key = action_key
|
|
||||||
|
|
||||||
def on_enter_callback(self, previous_mode):
|
|
||||||
"""
|
"""
|
||||||
presses e to throw the fishing rod
|
presses e to throw the fishing rod
|
||||||
:param previous_mode: previous mode in the state machine
|
|
||||||
"""
|
"""
|
||||||
keyboard.press_and_release(self.action_key)
|
keyboard.press_and_release(FishEvent.action_key)
|
||||||
_notify("look")
|
|
||||||
|
|
||||||
def on_exit_callback(self, current_mode):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class IdleEvent(FishEvent):
|
def on_idle():
|
||||||
"""
|
if FishEvent.fishCaught > 0:
|
||||||
State when the fishing hole is depleted or the bot is doing nothing
|
web.send_hole_deplete(FishEvent.uid, FishEvent.fishCaught, time.time() - FishEvent.hole_start_time,
|
||||||
"""
|
FishEvent.fish_times)
|
||||||
|
FishEvent.fishCaught = 0
|
||||||
def __init__(self, uid, sound: bool):
|
if FishEvent.sound:
|
||||||
"""
|
|
||||||
sets the flag to send notification on phone
|
|
||||||
"""
|
|
||||||
self.uid = uid
|
|
||||||
self.sound = sound
|
|
||||||
|
|
||||||
def on_enter_callback(self, previous_mode):
|
|
||||||
"""
|
|
||||||
Resets the fishCaught counter and logs a message depending on the previous state
|
|
||||||
:param previous_mode: previous mode in the state machine
|
|
||||||
"""
|
|
||||||
global _fishCaught
|
|
||||||
|
|
||||||
if _fishCaught > 0:
|
|
||||||
web.send_hole_deplete(self.uid, _fishCaught, time.time() - _hole_start_time, _fish_times)
|
|
||||||
_fishCaught = 0
|
|
||||||
if self.sound:
|
|
||||||
playsound(helper.manifest_file("sound.mp3"), False)
|
playsound(helper.manifest_file("sound.mp3"), False)
|
||||||
|
|
||||||
if previous_mode.name == "hook":
|
if FishEvent.previousState == State.HOOK:
|
||||||
logging.info("HOLE DEPLETED")
|
logging.info("HOLE DEPLETED")
|
||||||
else:
|
else:
|
||||||
logging.info("FISHING INTERRUPTED")
|
logging.info("FISHING INTERRUPTED")
|
||||||
|
|
||||||
_notify("idle")
|
|
||||||
|
|
||||||
def on_exit_callback(self, current_mode):
|
def on_stick():
|
||||||
pass
|
FishEvent.stickInitTime = time.time()
|
||||||
|
FishEvent.FishingStarted = True
|
||||||
|
|
||||||
|
if FishEvent.fishCaught == 0:
|
||||||
class StickEvent(FishEvent):
|
FishEvent.hole_start_time = time.time()
|
||||||
"""
|
FishEvent.fish_times = []
|
||||||
State when fishing is going on
|
|
||||||
"""
|
|
||||||
|
|
||||||
def on_enter_callback(self, previous_mode):
|
|
||||||
"""
|
|
||||||
resets the fishing timer
|
|
||||||
:param previous_mode: previous mode in the state machine
|
|
||||||
"""
|
|
||||||
global _stickInitTime, _hole_start_time, _fish_times, _FishingStarted
|
|
||||||
|
|
||||||
_stickInitTime = time.time()
|
|
||||||
_FishingStarted = True
|
|
||||||
|
|
||||||
if _fishCaught == 0:
|
|
||||||
_hole_start_time = time.time()
|
|
||||||
_fish_times = []
|
|
||||||
|
|
||||||
_notify("stick")
|
|
||||||
|
|
||||||
def on_exit_callback(self, current_mode):
|
|
||||||
pass
|
|
||||||
|
@ -1,70 +1,38 @@
|
|||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
subscribers = []
|
||||||
|
|
||||||
|
|
||||||
|
class State(Enum):
|
||||||
|
HOOK = 60,
|
||||||
|
STICK = 18,
|
||||||
|
LOOK = 100,
|
||||||
|
IDLE = -1
|
||||||
|
|
||||||
|
|
||||||
|
def _notify(event):
|
||||||
|
for subscriber in subscribers:
|
||||||
|
subscriber(event)
|
||||||
|
|
||||||
|
|
||||||
class FishingMode:
|
class FishingMode:
|
||||||
"""
|
CurrentMode = State.IDLE
|
||||||
State machine for fishing modes
|
PrevMode = State.IDLE
|
||||||
|
|
||||||
HValues hue values for each fishing mode
|
|
||||||
CurrentCount number of times same hue color is read before it changes state
|
|
||||||
CurrentMode current mode of the state machine
|
|
||||||
PrevMode previous mode of the state machine
|
|
||||||
FishingStarted probably does nothing (not sure though)
|
|
||||||
Modes list of states
|
|
||||||
"""
|
|
||||||
HValues = [60, 18, 100]
|
|
||||||
|
|
||||||
CurrentMode = None
|
def loop(hue_values):
|
||||||
PrevMode = None
|
|
||||||
|
|
||||||
Modes = []
|
|
||||||
|
|
||||||
def __init__(self, name, label, event):
|
|
||||||
"""
|
|
||||||
create a new state
|
|
||||||
:param name: name of the state
|
|
||||||
:param label: integer, label of the state (int)
|
|
||||||
:param event: object of class containing onEnterCallback & onExitCallback functions
|
|
||||||
which are called when state is changed
|
|
||||||
"""
|
|
||||||
self.name = name
|
|
||||||
self.label = label
|
|
||||||
self.event = event
|
|
||||||
|
|
||||||
FishingMode.Modes.append(self)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_by_label(label):
|
|
||||||
"""
|
|
||||||
find a state using label
|
|
||||||
:param label: label integer
|
|
||||||
:return: state
|
|
||||||
"""
|
|
||||||
for m in FishingMode.Modes:
|
|
||||||
if m.label == label:
|
|
||||||
return m
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def loop(hue_values):
|
|
||||||
"""
|
"""
|
||||||
Executed in the start of the main loop in fishy.py
|
Executed in the start of the main loop in fishy.py
|
||||||
Changes modes, calls mode events (callbacks) when mode is changed
|
Changes modes, calls mode events (callbacks) when mode is changed
|
||||||
|
|
||||||
:param hue_values: hue_values read by the bot
|
:param hue_values: hue_values read by the bot
|
||||||
"""
|
"""
|
||||||
if FishingMode.PrevMode is None:
|
FishingMode.CurrentMode = State.IDLE
|
||||||
FishingMode.PrevMode = FishingMode.get_by_label(3)
|
for s in State:
|
||||||
|
if hue_values == s.value:
|
||||||
current_label = 3
|
FishingMode.CurrentMode = s
|
||||||
for i, val in enumerate(FishingMode.HValues):
|
|
||||||
if hue_values == val:
|
|
||||||
current_label = i
|
|
||||||
|
|
||||||
FishingMode.CurrentMode = FishingMode.get_by_label(current_label)
|
|
||||||
|
|
||||||
if FishingMode.CurrentMode != FishingMode.PrevMode:
|
if FishingMode.CurrentMode != FishingMode.PrevMode:
|
||||||
|
_notify(FishingMode.CurrentMode)
|
||||||
if FishingMode.PrevMode.event is not None:
|
|
||||||
FishingMode.PrevMode.event.on_exit_callback(FishingMode.CurrentMode)
|
|
||||||
|
|
||||||
if FishingMode.CurrentMode.event is not None:
|
|
||||||
FishingMode.CurrentMode.event.on_enter_callback(FishingMode.PrevMode)
|
|
||||||
|
|
||||||
FishingMode.PrevMode = FishingMode.CurrentMode
|
FishingMode.PrevMode = FishingMode.CurrentMode
|
||||||
|
Loading…
Reference in New Issue
Block a user