connected mode select in config with the engine

- restructed player and recorder to work with new system,
- remove FullAuto.State
This commit is contained in:
Adam Saudagar 2021-05-02 21:09:59 +05:30
parent 1290c877f1
commit 3ce3c24dd1
9 changed files with 174 additions and 150 deletions

View File

@ -4,8 +4,6 @@ from pynput.keyboard import Key
from fishy.helper import hotkey
from fishy.engine.fullautofisher.engine import FullAuto, State
def get_controls(controls: 'Controls'):
controls = [
@ -36,10 +34,6 @@ class Controls:
logging.info(help_str)
def select_mode(self, mode):
if FullAuto.state != State.NONE:
self.log_help()
return
self.current_menu = 0
for i, control in enumerate(self.controls):
if mode == control[0]:

View File

@ -8,6 +8,9 @@ import logging
import time
from fishy.constants import libgps, fishyqr, lam2
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_values_from_image, get_qr_location
from fishy.engine.semifisher.fishing_mode import FishingMode
@ -19,7 +22,8 @@ from fishy.engine.common.IEngine import IEngine
from pynput import keyboard, mouse
from fishy.helper import hotkey, helper
from fishy.helper.helper import sign
from fishy.helper.helper import sign, log_raise
from fishy.helper.config import config
mse = mouse.Controller()
kb = keyboard.Controller()
@ -34,16 +38,8 @@ def image_pre_process(img):
return img
class State(Enum):
NONE = 0
PLAYING = 1
RECORDING = 2
OTHER = 3
class FullAuto(IEngine):
rotate_by = 30
state = State.NONE
def __init__(self, gui_ref):
from fishy.engine.fullautofisher.calibrator import Calibrator
@ -58,6 +54,8 @@ class FullAuto(IEngine):
self.test = Test(self)
self.show_crop = False
self.mode = None
def run(self):
addons_req = [libgps, lam2, fishyqr]
@ -65,34 +63,33 @@ class FullAuto(IEngine):
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")
self.mode = Player(self) if FullAutoMode(config.get("full_auto_mode", 0)) == FullAutoMode.Player else Recorder(self)
# todo use config to run player or recorder
# noinspection PyBroadException
try:
if self.window.get_capture() is None:
log_raise("Game window not found")
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")
log_raise("FishyQR not found")
if not self.calibrator.all_callibrated():
logging.error("you need to calibrate first")
log_raise("you need to calibrate first")
self.fisher.toggle_start()
fishing_event.unsubscribe()
if self.show_crop:
self.start_show()
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:
self.mode.run()
except Exception:
traceback.print_exc()
if self.window.get_capture() is None:
logging.error("Game window not found")
self.start = False
self.gui.bot_started(False)
self.window.show(False)
@ -100,6 +97,12 @@ class FullAuto(IEngine):
self.window.destory()
self.fisher.toggle_start()
def start_show(self):
def func():
while self.start and WindowClient.running():
self.window.show(self.show_crop, func=image_pre_process)
Thread(target=func).start()
def get_coods(self):
img = self.window.processed_image(func=image_pre_process)
return get_values_from_image(img)
@ -191,10 +194,6 @@ class FullAuto(IEngine):
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)

View File

@ -0,0 +1,14 @@
from abc import ABC, abstractmethod
from enum import Enum
class FullAutoMode(Enum):
Player = 0
Recorder = 1
class IMode(ABC):
@abstractmethod
def run(self):
...

View File

@ -0,0 +1,92 @@
import logging
import pickle
from pprint import pprint
import typing
from threading import Thread
from fishy.engine.fullautofisher.mode.imode import IMode
from fishy.engine.semifisher import fishing_event, fishing_mode
from fishy.helper.helper import log_raise, wait_until, kill_thread
if typing.TYPE_CHECKING:
from fishy.engine.fullautofisher.engine import FullAuto
from fishy.helper import helper
from fishy.helper.config import config
def _get_rec_file():
file = config.get("full_auto_rec_file")
if not file:
logging.error("Please select a fishy file first from config")
return None
file = open(file, 'rb')
data = pickle.load(file)
file.close()
pprint(data)
if "full_auto_path" not in data:
logging.error("invalid file")
return None
return data["full_auto_path"]
class Player(IMode):
def __init__(self, engine: 'FullAuto'):
self.recording = False
self.engine = engine
self.hole_complete_flag = False
self.start_moving_flag = False
self.i = 0
self.forward = True
self.timeline = None
def run(self):
self._init()
while self.engine.start:
self._loop()
logging.info("player stopped")
def _init(self):
self.timeline = _get_rec_file()
if not self.timeline:
log_raise("data not found, can't start")
logging.info("starting player")
def _loop(self):
action = self.timeline[self.i]
if action[0] == "move_to":
self.engine.move_to(action[1])
elif action[0] == "check_fish":
self.engine.move_to(action[1])
self.engine.rotate_to(action[1][2])
fishing_event.subscribe()
fishing_mode.subscribers.append(self._hole_complete_callback)
# scan for fish hole
logging.info("scanning")
# if found start fishing and wait for hole to complete
if self.engine.look_for_hole():
logging.info("starting fishing")
self.hole_complete_flag = False
helper.wait_until(lambda: self.hole_complete_flag or not self.engine.start)
self.engine.rotate_back()
else:
logging.info("no hole found")
# continue when hole completes
fishing_event.unsubscribe()
fishing_mode.subscribers.remove(self._hole_complete_callback)
self.i += 1 if self.forward else -1
if self.i >= len(self.timeline):
self.forward = False
self.i = len(self.timeline) - 1
elif self.i < 0:
self.forward = True
self.i = 0
def _hole_complete_callback(self, e):
if e == fishing_event.State.IDLE:
self.hole_complete_flag = True

View File

@ -4,17 +4,21 @@ import time
from pprint import pprint
from tkinter.filedialog import asksaveasfile
from fishy.engine.fullautofisher.engine import FullAuto, State
import typing
if typing.TYPE_CHECKING:
from fishy.engine.fullautofisher.engine import FullAuto
from fishy.engine.fullautofisher.mode.imode import IMode
from fishy.helper.hotkey import Key
from fishy.helper.hotkey_process import HotKey
class Recorder:
class Recorder(IMode):
recording_fps = 1
mark_hole_key = Key.F8
def __init__(self, engine: FullAuto):
def __init__(self, engine: 'FullAuto'):
self.recording = False
self.engine = engine
self.timeline = []
@ -24,23 +28,14 @@ class Recorder:
self.timeline.append(("check_fish", coods))
logging.info("check_fish")
def toggle_recording(self):
if FullAuto.state != State.RECORDING and FullAuto.state != State.NONE:
return
self.recording = not self.recording
if self.recording:
self._start_recording()
def _start_recording(self):
FullAuto.state = State.RECORDING
def run(self):
logging.info("starting, press f8 to mark hole")
hk = HotKey()
hk.start_process(self._mark_hole)
self.timeline = []
while self.recording:
while self.engine.start:
start_time = time.time()
coods = None
while not coods:
@ -68,5 +63,4 @@ class Recorder:
pprint(data)
pickle.dump(data, file)
file.close()
FullAuto.state = State.NONE

View File

@ -1,95 +0,0 @@
import logging
import pickle
from pprint import pprint
from fishy.engine.semifisher import fishing_event, fishing_mode
from fishy.engine.fullautofisher.engine import FullAuto, State
from fishy.helper import helper
from fishy.helper.config import config
def _get_rec_file():
file = config.get("full_auto_rec_file")
if not file:
logging.error("Please select a fishy file first from config")
return None
file = open(file, 'rb')
data = pickle.load(file)
file.close()
pprint(data)
if "full_auto_path" not in data:
logging.error("invalid file")
return None
return data["full_auto_path"]
class Player:
def __init__(self, engine: 'FullAuto'):
self.recording = False
self.engine = engine
self.hole_complete_flag = False
self.start_moving_flag = False
def toggle_move(self):
if FullAuto.state != State.PLAYING and FullAuto.state != State.NONE:
return
self.start_moving_flag = not self.start_moving_flag
if self.start_moving_flag:
self._start_route()
else:
logging.info("Waiting for the last action to finish...")
def _hole_complete_callback(self, e):
if e == fishing_event.State.IDLE:
self.hole_complete_flag = True
def _start_route(self):
timeline = _get_rec_file()
if not timeline:
logging.log("data not found, can't start")
return
FullAuto.state = State.PLAYING
logging.info("starting to move")
forward = True
i = 0
while self.start_moving_flag:
action = timeline[i]
if action[0] == "move_to":
self.engine.move_to(action[1])
elif action[0] == "check_fish":
self.engine.move_to(action[1])
self.engine.rotate_to(action[1][2])
fishing_event.subscribe()
fishing_mode.subscribers.append(self._hole_complete_callback)
# scan for fish hole
logging.info("scanning")
if self.engine.look_for_hole():
logging.info("starting fishing")
self.hole_complete_flag = False
helper.wait_until(lambda: self.hole_complete_flag or not self.start_moving_flag)
self.engine.rotate_back()
else:
logging.info("no hole found")
# if found start fishing and wait for hole to complete
# contine when hole completes
fishing_event.unsubscribe()
fishing_mode.subscribers.remove(self._hole_complete_callback)
i += 1 if forward else -1
if i >= len(timeline):
forward = False
i = len(timeline) - 1
elif i < 0:
forward = True
i = 0
logging.info("stopped")
FullAuto.state = State.NONE

View File

@ -4,6 +4,7 @@ import typing
from tkinter.filedialog import askopenfilename
from fishy.engine.common.event_handler import IEngineHandler
from fishy.engine.fullautofisher.mode.imode import FullAutoMode
from fishy.helper import helper
from fishy import web
@ -42,17 +43,17 @@ def start_fullfisher_config(gui: 'GUI'):
def start_calibrate():
...
def select_radio():
...
def mode_command():
config.set("full_auto_mode", mode_var.get())
file_name_label = StringVar(value=file_name())
radio_var = IntVar()
mode_var = IntVar(value=config.get("full_auto_mode", 0))
Button(controls_frame, text="Recalibrate", command=start_calibrate).grid(row=0, column=0, columnspan=2, pady=(5, 5))
Button(controls_frame, text="Calibrate", command=start_calibrate).grid(row=0, column=0, columnspan=2, pady=(5, 5))
Label(controls_frame, text="Mode: ").grid(row=1, column=0, pady=(5, 0))
Radiobutton(controls_frame, text="Player", variable=radio_var, value=0, command=select_radio).grid(row=1, column=1, sticky="w")
Radiobutton(controls_frame, text="Recorder", variable=radio_var, value=1, command=select_radio).grid(row=2, column=1, sticky="w", pady=(0, 5))
Radiobutton(controls_frame, text="Player", variable=mode_var, value=FullAutoMode.Player.value, command=mode_command).grid(row=1, column=1, sticky="w")
Radiobutton(controls_frame, text="Recorder", variable=mode_var, value=FullAutoMode.Recorder.value, command=mode_command).grid(row=2, column=1, sticky="w", pady=(0, 5))
Button(controls_frame, text="Select fishy file", command=select_file).grid(row=3, column=0, columnspan=2, pady=(5, 0))
Label(controls_frame, textvariable=file_name_label).grid(row=4, column=0, columnspan=2, pady=(0, 5))

View File

@ -1,3 +1,4 @@
import ctypes
import logging
import os
import shutil
@ -202,8 +203,32 @@ def restart():
os.execl(sys.executable, *([sys.executable] + sys.argv))
def log_raise(msg):
logging.error(msg)
raise Exception(msg)
def update():
from .config import config
config.delete("dont_ask_update")
restart()
# noinspection PyProtectedMember,PyUnresolvedReferences
def _get_id(thread):
# returns id of the respective thread
if hasattr(thread, '_thread_id'):
return thread._thread_id
for id, thread in threading._active.items():
if thread is thread:
return id
def kill_thread(thread):
thread_id = _get_id(thread)
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,
ctypes.py_object(SystemExit))
if res > 1:
ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0)
print('Exception raise failure')