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.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 pynput import keyboard, mouse
|
||||
@ -171,7 +171,7 @@ class FullAuto(IEngine):
|
||||
if e == "look":
|
||||
self._hole_found_flag = True
|
||||
|
||||
fishing_event.subscribers.append(found_hole)
|
||||
fishing_mode.subscribers.append(found_hole)
|
||||
|
||||
t = 0
|
||||
while not self._hole_found_flag and t <= self.factors[2] / 2:
|
||||
@ -184,7 +184,7 @@ class FullAuto(IEngine):
|
||||
t -= 0.05
|
||||
|
||||
self._curr_rotate_y = t
|
||||
fishing_event.subscribers.remove(found_hole)
|
||||
fishing_mode.subscribers.remove(found_hole)
|
||||
return self._hole_found_flag
|
||||
|
||||
def set_target(self):
|
||||
|
@ -1,19 +1,19 @@
|
||||
import time
|
||||
import typing
|
||||
from collections import Callable
|
||||
from threading import Thread
|
||||
from typing import Callable
|
||||
|
||||
import cv2
|
||||
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.semifisher import fishing_event
|
||||
from .fishing_event import HookEvent, StickEvent, LookEvent, IdleEvent
|
||||
from .fishing_mode import FishingMode
|
||||
from .pixel_loc import PixelLoc
|
||||
from ..common.window import WindowClient
|
||||
from fishy.engine.semifisher import fishing_mode, fishing_event
|
||||
from fishy.engine.semifisher.pixel_loc import PixelLoc
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from fishy.gui import GUI
|
||||
@ -29,15 +29,7 @@ class SemiFisherEngine(IEngine):
|
||||
Starts the fishing
|
||||
code explained in comments in detail
|
||||
"""
|
||||
|
||||
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")))
|
||||
|
||||
fishing_event.init()
|
||||
self.fishPixWindow = WindowClient(color=cv2.COLOR_RGB2HSV)
|
||||
|
||||
# check for game window and stuff
|
||||
@ -55,13 +47,15 @@ class SemiFisherEngine(IEngine):
|
||||
|
||||
self.fishPixWindow.crop = PixelLoc.val
|
||||
hue_value = capture[0][0][0]
|
||||
FishingMode.loop(hue_value)
|
||||
fishing_mode.loop(hue_value)
|
||||
|
||||
logging.info("Fishing engine stopped")
|
||||
self.gui.bot_started(False)
|
||||
fishing_event.destroy()
|
||||
|
||||
def _wait_and_check(self):
|
||||
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"
|
||||
"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()
|
||||
|
||||
|
||||
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 time
|
||||
from abc import abstractmethod, ABC
|
||||
|
||||
from fishy.engine.semifisher import fishing_mode
|
||||
from playsound import playsound
|
||||
|
||||
from fishy import web
|
||||
from fishy.engine.semifisher.fishing_mode import State
|
||||
from fishy.helper import helper
|
||||
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):
|
||||
for subscriber in subscribers:
|
||||
subscriber(event)
|
||||
def init():
|
||||
# todo load config
|
||||
fishing_mode.subscribers.append(fisher_callback)
|
||||
|
||||
|
||||
class FishEvent(ABC):
|
||||
@abstractmethod
|
||||
def on_enter_callback(self, previous_mode):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def on_exit_callback(self, current_mode):
|
||||
pass
|
||||
def destroy():
|
||||
fishing_mode.subscribers.remove(fisher_callback)
|
||||
|
||||
|
||||
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
|
||||
increases the `fishCaught` and `totalFishCaught`, calculates the time it took to catch
|
||||
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
|
||||
_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)
|
||||
keyboard.press_and_release(FishEvent.action_key)
|
||||
|
||||
if self.collect_r:
|
||||
if FishEvent.collect_r:
|
||||
time.sleep(0.1)
|
||||
keyboard.press_and_release('r')
|
||||
time.sleep(0.1)
|
||||
|
||||
_notify("hook")
|
||||
|
||||
|
||||
|
||||
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):
|
||||
def on_look():
|
||||
"""
|
||||
presses e to throw the fishing rod
|
||||
:param previous_mode: previous mode in the state machine
|
||||
"""
|
||||
keyboard.press_and_release(self.action_key)
|
||||
_notify("look")
|
||||
|
||||
def on_exit_callback(self, current_mode):
|
||||
pass
|
||||
keyboard.press_and_release(FishEvent.action_key)
|
||||
|
||||
|
||||
class IdleEvent(FishEvent):
|
||||
"""
|
||||
State when the fishing hole is depleted or the bot is doing nothing
|
||||
"""
|
||||
|
||||
def __init__(self, uid, sound: bool):
|
||||
"""
|
||||
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:
|
||||
def on_idle():
|
||||
if FishEvent.fishCaught > 0:
|
||||
web.send_hole_deplete(FishEvent.uid, FishEvent.fishCaught, time.time() - FishEvent.hole_start_time,
|
||||
FishEvent.fish_times)
|
||||
FishEvent.fishCaught = 0
|
||||
if FishEvent.sound:
|
||||
playsound(helper.manifest_file("sound.mp3"), False)
|
||||
|
||||
if previous_mode.name == "hook":
|
||||
if FishEvent.previousState == State.HOOK:
|
||||
logging.info("HOLE DEPLETED")
|
||||
else:
|
||||
logging.info("FISHING INTERRUPTED")
|
||||
|
||||
_notify("idle")
|
||||
|
||||
def on_exit_callback(self, current_mode):
|
||||
pass
|
||||
def on_stick():
|
||||
FishEvent.stickInitTime = time.time()
|
||||
FishEvent.FishingStarted = True
|
||||
|
||||
|
||||
class StickEvent(FishEvent):
|
||||
"""
|
||||
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
|
||||
if FishEvent.fishCaught == 0:
|
||||
FishEvent.hole_start_time = time.time()
|
||||
FishEvent.fish_times = []
|
||||
|
@ -1,47 +1,25 @@
|
||||
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:
|
||||
"""
|
||||
State machine for fishing modes
|
||||
CurrentMode = State.IDLE
|
||||
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
|
||||
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
|
||||
@ -49,22 +27,12 @@ class FishingMode:
|
||||
|
||||
:param hue_values: hue_values read by the bot
|
||||
"""
|
||||
if FishingMode.PrevMode is None:
|
||||
FishingMode.PrevMode = FishingMode.get_by_label(3)
|
||||
|
||||
current_label = 3
|
||||
for i, val in enumerate(FishingMode.HValues):
|
||||
if hue_values == val:
|
||||
current_label = i
|
||||
|
||||
FishingMode.CurrentMode = FishingMode.get_by_label(current_label)
|
||||
FishingMode.CurrentMode = State.IDLE
|
||||
for s in State:
|
||||
if hue_values == s.value:
|
||||
FishingMode.CurrentMode = s
|
||||
|
||||
if FishingMode.CurrentMode != FishingMode.PrevMode:
|
||||
|
||||
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)
|
||||
_notify(FishingMode.CurrentMode)
|
||||
|
||||
FishingMode.PrevMode = FishingMode.CurrentMode
|
||||
|
Loading…
Reference in New Issue
Block a user