states for when playing/recording is running, added error message when window is not found in full auto, added beep sound when hotkey is pressed, made hotkey callable Optional

This commit is contained in:
Adam Saudagar
2020-11-19 18:49:27 +05:30
parent a51a301070
commit 367e2bea55
7 changed files with 137 additions and 92 deletions

View File

@ -6,6 +6,7 @@ include fishy/ProvisionsChalutier.zip
include fishy/FooAddon.zip
include fishy/fishybot_logo.png
include fishy/sound.mp3
include fishy/beep.wav
recursive-include tests *
recursive-exclude * __pycache__

BIN
fishy/beep.wav Normal file

Binary file not shown.

View File

@ -1,36 +1,46 @@
import logging
from fishy.helper import hotkey
from fishy.helper import hotkey, helper
from fishy.engine.fullautofisher.engine import FullAuto
from fishy.helper.config import config
from fishy.helper.hotkey import Key
def get_controls(engine: FullAuto):
from fishy.engine.fullautofisher.calibrate import Calibrate
from fishy.engine.fullautofisher.recorder import Recorder
from fishy.engine.fullautofisher.player import Player
controls = [
# ("MAIN", {
# Key.RIGHT: Player(engine).start_route,
# Key.UP: Calibrate(engine).callibrate,
# Key.LEFT: Recorder(engine).start_recording,
# Key.DOWN: change_state
# }),
# ("COODS", {
# Key.RIGHT: print_coods,
# Key.UP: engine.update_crop,
# Key.LEFT: toggle_show,
# Key.DOWN: change_state
# }),
# ("TEST1", {
# Key.RIGHT: set_target,
# Key.UP: rotate_to_90,
# Key.LEFT: move_to_target,
# Key.DOWN: change_state
# })
("MODE_SELECT", {
Key.RIGHT: (lambda: engine.controls.select_mode("CALIBRATE"), "calibrate mode"),
Key.UP: (lambda: engine.controls.select_mode("PLAY"), "play mode"),
Key.LEFT: (lambda: engine.controls.select_mode("RECORD"), "record mode"),
Key.DOWN: (lambda: engine.controls.select_mode("TEST"), "test mode")
}),
("CALIBRATE", {
Key.RIGHT: (engine.calibrate.update_crop, "cropping"),
Key.UP: (engine.calibrate.walk_calibrate, "walking"),
Key.LEFT: (engine.calibrate.rotate_calibrate, "rotation"),
Key.DOWN: (engine.calibrate.time_to_reach_bottom_callibrate, "look up down")
}),
("PLAY/RECORD", {
Key.RIGHT: (Player(engine).toggle_move, "start/stop play"),
Key.UP: (Recorder(engine).toggle_recording, "start/stop record"),
Key.LEFT: (None, "not implemented"),
Key.DOWN: (None, "not implemented")
}),
("TEST1", {
Key.RIGHT: (engine.test.print_coods, "print coordinates"),
Key.UP: (engine.test.look_for_hole, "look for hole up down"),
Key.LEFT: (None, "not implemented"),
Key.DOWN: (lambda: engine.controls.select_mode("TEST2"), "show next")
}),
("TEST2", {
Key.RIGHT: (engine.test.set_target, "set target"),
Key.UP: (engine.test.move_to_target, "move to target"),
Key.LEFT: (engine.test.rotate_to_target, "rotate to target"),
Key.DOWN: (lambda: engine.controls.select_mode("TEST1"), "show previous")
})
]
return controls
@ -41,15 +51,20 @@ class Controls:
self.current_menu = first - 1
self.controls = controls
def change_state(self):
self.current_menu += 1
if self.current_menu == len(self.controls):
self.current_menu = 0
def initialize(self):
self.select_mode("MODE_SELECT")
def select_mode(self, mode):
self.current_menu = 0
for i, control in enumerate(self.controls):
if mode == control[0]:
self.current_menu = i
help_str = F"CONTROLS: {self.controls[self.current_menu][0]}"
for key, func in self.controls[self.current_menu][1].items():
for key, meta in self.controls[self.current_menu][1].items():
func, name = meta
hotkey.set_hotkey(key, func)
help_str += f"\n{key.value}: {func.__name__}"
help_str += f"\n{key.value}: {name}"
logging.info(help_str)
def unassign_keys(self):
@ -57,4 +72,4 @@ class Controls:
for c in self.controls:
for k in c[1].keys():
if k not in keys:
hotkey.free_key(k)
hotkey.free_key(k)

View File

@ -1,7 +1,9 @@
import math
import os
import tempfile
import traceback
import uuid
from enum import Enum
from zipfile import ZipFile
import cv2
@ -42,8 +44,16 @@ 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.controls import Controls
@ -56,9 +66,9 @@ class FullAuto(IEngine):
self._curr_rotate_y = 0
self.fisher = SemiFisherEngine(None)
self.controls = Controls(controls.get_controls(self))
self.calibrate = Calibrate(self)
self.test = Test(self)
self.controls = Controls(controls.get_controls(self))
@property
def show_crop(self):
@ -75,24 +85,31 @@ class FullAuto(IEngine):
self.fisher.toggle_start()
self.window = WindowClient(color=cv2.COLOR_RGB2GRAY, show_name="Full auto debug")
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()
try:
if self.calibrate.crop is None:
self.calibrate.update_crop(enable_crop=False)
self.window.crop = self.calibrate.crop
self.controls.change_state()
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)
if not is_tesseract_installed():
logging.info("tesseract not found")
downlaoad_and_extract_tesseract()
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 not self.window.get_capture():
logging.error("Game window not found")
self.gui.bot_started(False)
self.controls.unassign_keys()
self.window.show(False)
logging.info("Quit")
logging.info("Quitting")
self.window.destory()
self.fisher.toggle_start()

View File

@ -4,63 +4,59 @@ from pprint import pprint
from fishy.engine.semifisher import fishing_event, fishing_mode
from fishy.engine.fullautofisher.engine import FullAuto
from fishy.engine.fullautofisher.engine import FullAuto, State
from fishy.helper import hotkey, helper
from fishy.helper import helper
from fishy.helper.config import config
from fishy.helper.hotkey import Key
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.timeline = []
self.hole_complete_flag = False
self.start_moving_flag = False
def _mark_hole(self):
coods = self.engine.get_coods()
self.timeline.append(("check_fish", coods))
def toggle_move(self):
if FullAuto.state != State.PLAYING and FullAuto.state != State.NONE:
return
def _start_moving(self):
self.start_moving_flag = not self.start_moving_flag
def _stop_recording(self):
self.recording = False
if self.start_moving_flag:
self._start_route()
def _hole_complete_callback(self, e):
if e == fishing_event.State.IDLE:
self.hole_complete_flag = True
def start_route(self):
file = config.get("full_auto_rec_file")
if not file:
logging.error("Please select a fishy file first from config")
def _start_route(self):
FullAuto.state = State.PLAYING
timeline = _get_rec_file()
if not timeline:
return
file = open(file, 'rb')
data = pickle.load(file)
file.close()
pprint(data)
if "full_auto_path" not in data:
logging.error("invalid file")
return
self.timeline = data["full_auto_path"]
# wait until f8 is pressed
logging.info("press f8 to start")
self.start_moving_flag = False
hotkey.set_hotkey(Key.F8, self._start_moving)
helper.wait_until(lambda: self.start_moving_flag)
logging.info("starting, press f8 to stop")
forward = True
i = 0
while self.start_moving_flag:
action = self.timeline[i]
action = timeline[i]
if action[0] == "move_to":
self.engine.move_to(action[1])
@ -84,11 +80,12 @@ class Player:
fishing_mode.subscribers.remove(self._hole_complete_callback)
i += 1 if forward else -1
if i >= len(self.timeline):
if i >= len(timeline):
forward = False
i = len(self.timeline) - 1
i = len(timeline) - 1
elif i < 0:
forward = True
i = 0
logging.info("stopped")
FullAuto.state = State.NONE

View File

@ -4,7 +4,7 @@ import time
from pprint import pprint
from tkinter.filedialog import asksaveasfile
from fishy.engine.fullautofisher.engine import FullAuto
from fishy.engine.fullautofisher.engine import FullAuto, State
from fishy.helper import hotkey
from fishy.helper.hotkey import Key
@ -12,6 +12,7 @@ from fishy.helper.hotkey import Key
class Recorder:
recording_fps = 1
mark_hole_key = Key.F8
def __init__(self, engine: FullAuto):
self.recording = False
@ -23,15 +24,19 @@ class Recorder:
self.timeline.append(("check_fish", coods))
logging.info("check_fish")
def _stop_recording(self):
self.recording = False
def toggle_recording(self):
if FullAuto.state != State.RECORDING and FullAuto.state != State.NONE:
return
def start_recording(self):
logging.info("f7 for marking hole, f8 to stop recording")
hotkey.set_hotkey(Key.F7, self._mark_hole)
hotkey.set_hotkey(Key.F8, self._stop_recording)
self.recording = not self.recording
if self.recording:
self._start_recording()
def _start_recording(self):
FullAuto.state = State.RECORDING
logging.info("f8 to stop recording")
hotkey.set_hotkey(Recorder.mark_hole_key, self._mark_hole)
self.recording = True
self.timeline = []
while self.recording:
@ -47,6 +52,8 @@ class Recorder:
else:
logging.warning("Took too much time to record")
hotkey.free_key(Recorder.mark_hole_key)
files = [('Fishy File', '*.fishy')]
file = None
while not file:
@ -55,4 +62,5 @@ class Recorder:
pprint(data)
pickle.dump(data, file)
file.close()
FullAuto.state = State.NONE

View File

@ -1,8 +1,9 @@
from enum import Enum
from threading import Thread
from typing import Dict, Callable
from typing import Dict, Callable, Optional
import keyboard
from playsound import playsound
from fishy.helper import helper
@ -18,22 +19,28 @@ class Key(Enum):
RIGHT = "right"
_hotkeys: Dict[Key, Callable] = {}
_hotkeys: Dict[Key, Optional[Callable]] = {}
def _run_callback(k):
return lambda: Thread(target=_hotkeys[k]).start()
def _get_callback(k):
def callback():
if not _hotkeys[k]:
return
playsound(helper.manifest_file("beep.wav"), False)
Thread(target=_hotkeys[k]).start()
return callback
def initalize():
for k in Key:
_hotkeys[k] = helper.empty_function
keyboard.add_hotkey(k.value, _run_callback(k))
_hotkeys[k] = None
keyboard.add_hotkey(k.value, _get_callback(k))
def set_hotkey(key: Key, func: Callable):
def set_hotkey(key: Key, func: Optional[Callable]):
_hotkeys[key] = func
def free_key(k: Key):
set_hotkey(k, helper.empty_function)
set_hotkey(k, None)