mirror of
https://github.com/fishyboteso/fishyboteso.git
synced 2024-08-30 18:32:13 +00:00
gui interface re created for multi threading
This commit is contained in:
parent
ba20738cbf
commit
49fa3c6294
@ -13,14 +13,10 @@ Options:
|
||||
--borderless Use if the game is in fullscreen or borderless window
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
import cv2
|
||||
|
||||
from docopt import docopt
|
||||
from pynput.keyboard import Listener
|
||||
|
||||
from fishy.systems import *
|
||||
import logging
|
||||
|
||||
"""
|
||||
Start reading from `init.py`
|
||||
@ -59,10 +55,7 @@ def on_release(key):
|
||||
|
||||
elif c[0] == Control.Keywords.SwitchMode:
|
||||
Control.nextState()
|
||||
Log.ctrl()
|
||||
|
||||
elif c[0] == Control.Keywords.ClearPrintOnce:
|
||||
Log.clearPrintIds()
|
||||
logging.info(Control.getControlHelp())
|
||||
|
||||
|
||||
def hsv2rgb(img):
|
||||
@ -81,15 +74,13 @@ def startFishing():
|
||||
if use_net:
|
||||
net.initialize(G.arguments["--ip"])
|
||||
|
||||
sleepFor = 1
|
||||
|
||||
# initializes fishing modes and their callbacks
|
||||
FishingMode("hook", 0, HookEvent())
|
||||
FishingMode("stick", 1, StickEvent())
|
||||
FishingMode("look", 2, LookEvent())
|
||||
FishingMode("idle", 3, IdleEvent(use_net))
|
||||
|
||||
Log.ctrl()
|
||||
logging.info(Control.getControlHelp())
|
||||
|
||||
fishPixWindow = Window(color=cv2.COLOR_RGB2HSV)
|
||||
|
||||
@ -98,11 +89,9 @@ def startFishing():
|
||||
with Listener(on_release=on_release):
|
||||
while not G.stop:
|
||||
# record the time to calculate time taken to execute one loop
|
||||
current_time = time.time()
|
||||
|
||||
# Services to be ran in the start of the main loop
|
||||
Window.Loop()
|
||||
Log.Loop()
|
||||
|
||||
# get the PixelLoc and find the color values, to give it to `FishingMode.Loop`
|
||||
fishPixWindow.crop = PixelLoc.val
|
||||
@ -112,20 +101,11 @@ def startFishing():
|
||||
# if debug is on, show the color on the PixelLoc in a window and print the hue values of it
|
||||
if G.debug:
|
||||
fishPixWindow.show("pixloc", resize=200, func=hsv2rgb)
|
||||
Log.ou(str(FishingMode.CurrentMode.label) + ":" + str(fishPixWindow.getCapture()[0][0]))
|
||||
logging.debug(str(FishingMode.CurrentMode.label) + ":" + str(fishPixWindow.getCapture()[0][0]))
|
||||
|
||||
# Services to be ran in the end of the main loop
|
||||
Log.LoopEnd()
|
||||
Window.LoopEnd()
|
||||
|
||||
# calculate the time it took to execute one loop of code, if it is more than the expected time warn user
|
||||
frameTime = time.time() - current_time
|
||||
if frameTime < sleepFor:
|
||||
time.sleep(sleepFor - frameTime)
|
||||
else:
|
||||
Log.po(231, "Program taking more time than expected, this might slow your computer try increasing "
|
||||
"\"--check-frequency\".")
|
||||
|
||||
|
||||
def main():
|
||||
G.arguments = docopt(__doc__)
|
||||
|
@ -2,7 +2,6 @@ from fishy.systems.controls import Control
|
||||
from fishy.systems.fishing_event import HookEvent, StickEvent, LookEvent, IdleEvent
|
||||
from fishy.systems.fishing_mode import FishingMode
|
||||
from fishy.systems.globals import G
|
||||
from fishy.systems.log import Log
|
||||
from fishy.systems.pixel_loc import PixelLoc
|
||||
import fishy.systems.fishy_network as net
|
||||
from fishy.systems.window import Window
|
||||
|
1
fishy/systems/config.json
Normal file
1
fishy/systems/config.json
Normal file
@ -0,0 +1 @@
|
||||
{"dark_mode": true}
|
23
fishy/systems/config.py
Normal file
23
fishy/systems/config.py
Normal file
@ -0,0 +1,23 @@
|
||||
import json
|
||||
import os
|
||||
|
||||
filename = "config.json"
|
||||
|
||||
|
||||
class Config:
|
||||
|
||||
def __init__(self):
|
||||
self.config_dict = json.loads(open(filename).read()) if os.path.exists(filename) else dict()
|
||||
|
||||
def get(self, key, default=None):
|
||||
if key in self.config_dict:
|
||||
return self.config_dict[key]
|
||||
return default
|
||||
|
||||
def set(self, key, value):
|
||||
self.config_dict[key] = value
|
||||
self.save_config()
|
||||
|
||||
def save_config(self):
|
||||
with open(filename, 'w') as f:
|
||||
f.write(json.dumps(self.config_dict))
|
@ -1,97 +1,187 @@
|
||||
import time
|
||||
from enum import Enum
|
||||
from tkinter import *
|
||||
from tkinter.ttk import *
|
||||
from ttkthemes import ThemedTk
|
||||
from waiting import wait
|
||||
import threading
|
||||
|
||||
dark_mode = False
|
||||
from fishy.systems.config import Config
|
||||
|
||||
|
||||
def toggle_theme():
|
||||
global dark_mode
|
||||
dark_mode = not dark_mode
|
||||
apply_theme(dark_mode)
|
||||
root.destroy()
|
||||
class Callback(Enum):
|
||||
START = 0,
|
||||
SHORTCUT = 1,
|
||||
CHECK_PIXELVAL = 2,
|
||||
LOG_DUMP = 3
|
||||
|
||||
|
||||
def apply_theme(dark):
|
||||
root["theme"] = "equilux" if dark else "breeze"
|
||||
console["background"] = "#707070" if dark else "#ffffff"
|
||||
console["fg"] = "#ffffff" if dark else "#000000"
|
||||
class GUICallback:
|
||||
def __init__(self, start_callback=None,
|
||||
shortcut_callback=None,
|
||||
check_pixelval_callback=None,
|
||||
log_dump_callback=None
|
||||
):
|
||||
self.start_callback = start_callback
|
||||
self.shortcut_callback = shortcut_callback
|
||||
self.check_pixelval_callback = check_pixelval_callback
|
||||
self.log_dump_callback = log_dump_callback
|
||||
|
||||
def start():
|
||||
writeToLog(console, "yo")
|
||||
def call(self, callback_enum, args=None):
|
||||
to_call = None
|
||||
if callback_enum == Callback.START:
|
||||
to_call = self.start_callback
|
||||
elif callback_enum == Callback.SHORTCUT:
|
||||
to_call = self.shortcut_callback
|
||||
elif callback_enum == Callback.CHECK_PIXELVAL:
|
||||
to_call = self.check_pixelval_callback
|
||||
elif callback_enum == Callback.LOG_DUMP:
|
||||
to_call = self.log_dump_callback
|
||||
|
||||
if to_call is None:
|
||||
return
|
||||
|
||||
threading.Thread(target=to_call, args=(*args,)).start()
|
||||
|
||||
|
||||
def writeToLog(log, msg):
|
||||
numlines = log.index('end - 1 line').split('.')[0]
|
||||
log['state'] = 'normal'
|
||||
if int(numlines) >= 50: # delete old lines
|
||||
log.delete(1.0, 2.0)
|
||||
if log.index('end-1c') != '1.0': # new line for each log
|
||||
log.insert('end', '\n')
|
||||
log.insert('end', msg)
|
||||
log.see("end") # scroll to bottom
|
||||
log['state'] = 'disabled'
|
||||
class GUI:
|
||||
|
||||
def __init__(self, gui_callback=None,
|
||||
config: Config = None):
|
||||
self.callbacks = GUICallback() if gui_callback is None else gui_callback
|
||||
self.config = config
|
||||
self.start_restart = False
|
||||
self.destroyed = True
|
||||
self.root = None
|
||||
self._log_strings = []
|
||||
self.console = None
|
||||
|
||||
def create(self):
|
||||
self.root = ThemedTk(theme="equilux", background=True)
|
||||
self.root.title("Fiishybot for Elder Scrolls Online")
|
||||
self.root.geometry('650x550')
|
||||
|
||||
# region menu
|
||||
menubar = Menu(self.root)
|
||||
|
||||
filemenu = Menu(menubar, tearoff=0)
|
||||
filemenu.add_command(label="Create Shortcut", command=lambda: self.callbacks.call(Callback.SHORTCUT))
|
||||
filemenu.add_command(label="{} Dark Mode".format("Disable" if self.config.get("dark_mode", True) else "Enable"),
|
||||
command=self._toggle_mode)
|
||||
menubar.add_cascade(label="File", menu=filemenu)
|
||||
|
||||
debug_menu = Menu(menubar, tearoff=0)
|
||||
debug_menu.add_command(label="Check PixelVal",
|
||||
command=lambda: self.callbacks.call(Callback.CHECK_PIXELVAL))
|
||||
debug_menu.add_command(label="Log Dump")
|
||||
menubar.add_cascade(label="Debug", menu=debug_menu, command=lambda: self.callbacks.call(Callback.LOG_DUMP))
|
||||
self.root.config(menu=menubar)
|
||||
# endregion
|
||||
|
||||
# region console
|
||||
self.console = Text(self.root, state='disabled', wrap='none', background="#707070", fg="#ffffff")
|
||||
self.console.pack(fill=BOTH, expand=True, pady=(15, 15), padx=(5, 5))
|
||||
self.console.mark_set("sentinel", INSERT)
|
||||
self.console.config(state=DISABLED)
|
||||
|
||||
controls_frame = Frame(self.root)
|
||||
# endregion
|
||||
|
||||
# region controls
|
||||
left_frame = Frame(controls_frame)
|
||||
|
||||
Label(left_frame, text="IP").grid(row=0, column=0)
|
||||
ip = Entry(left_frame)
|
||||
ip.grid(row=0, column=1)
|
||||
|
||||
Label(left_frame, text="Fullscreen: ").grid(row=1, column=0, pady=(5, 5))
|
||||
borderless = Checkbutton(left_frame)
|
||||
borderless.grid(row=1, column=1)
|
||||
|
||||
left_frame.grid(row=0, column=0)
|
||||
|
||||
right_frame = Frame(controls_frame)
|
||||
|
||||
Label(right_frame, text="Action Key:").grid(row=0, column=0)
|
||||
action_key_entry = Entry(right_frame)
|
||||
action_key_entry.grid(row=0, column=1)
|
||||
action_key_entry.insert(0, "e")
|
||||
|
||||
Label(right_frame, text="Press start").grid(row=1, columnspan=2, pady=(5, 5))
|
||||
|
||||
right_frame.grid(row=0, column=1, padx=(50, 0))
|
||||
|
||||
controls_frame.pack()
|
||||
|
||||
Button(self.root, text="START", width=25,
|
||||
command=lambda: self.callbacks.call(Callback.START,
|
||||
(ip.get(), action_key_entry.get(), borderless.instate(['selected'])))
|
||||
).pack(pady=(15, 15))
|
||||
# endregion
|
||||
|
||||
self._apply_theme(self.config.get("dark_mode", True))
|
||||
self.root.update()
|
||||
self.root.minsize(self.root.winfo_width(), self.root.winfo_height())
|
||||
self.root.protocol("WM_DELETE_WINDOW", self._set_destroyed)
|
||||
self.destroyed = False
|
||||
while True:
|
||||
self.root.update()
|
||||
self._update_console()
|
||||
|
||||
if self.start_restart:
|
||||
self.root.destroy()
|
||||
self.root.quit()
|
||||
self.start_restart = False
|
||||
self.create()
|
||||
if self.destroyed:
|
||||
break
|
||||
time.sleep(0.01)
|
||||
|
||||
def _apply_theme(self, dark):
|
||||
self.root["theme"] = "equilux" if dark else "breeze"
|
||||
self.console["background"] = "#707070" if dark else "#ffffff"
|
||||
self.console["fg"] = "#ffffff" if dark else "#000000"
|
||||
|
||||
def start(self):
|
||||
threading.Thread(target=self.create, args=()).start()
|
||||
|
||||
def _toggle_mode(self):
|
||||
self.config.set("dark_mode", not self.config.get("dark_mode", True))
|
||||
self.start_restart = True
|
||||
|
||||
def _set_destroyed(self):
|
||||
self.destroyed = True
|
||||
|
||||
def writeToLog(self, msg):
|
||||
self._log_strings.append(msg)
|
||||
|
||||
def _update_console(self):
|
||||
while len(self._log_strings) > 0:
|
||||
msg = self._log_strings.pop(0)
|
||||
numlines = self.console.index('end - 1 line').split('.')[0]
|
||||
self.console['state'] = 'normal'
|
||||
if int(numlines) >= 50: # delete old lines
|
||||
self.console.delete(1.0, 2.0)
|
||||
if self.console.index('end-1c') != '1.0': # new line for each log
|
||||
self.console.insert('end', '\n')
|
||||
self.console.insert('end', msg)
|
||||
self.console.see("end") # scroll to bottom
|
||||
self.console['state'] = 'disabled'
|
||||
|
||||
|
||||
while True:
|
||||
root = ThemedTk(theme="equilux", background=True)
|
||||
root.title("Fiishybot for Elder Scrolls Online")
|
||||
root.geometry('650x550')
|
||||
def start(ip, actionkey, fullscreen):
|
||||
print(f"{ip}, {actionkey}, {fullscreen}")
|
||||
|
||||
|
||||
# region menu
|
||||
menubar = Menu(root)
|
||||
def main():
|
||||
config = Config()
|
||||
gui = GUI(config=config, gui_callback=GUICallback(start_callback=start))
|
||||
gui.start()
|
||||
wait(lambda: not gui.destroyed)
|
||||
while not gui.destroyed:
|
||||
gui.writeToLog("yo")
|
||||
time.sleep(1)
|
||||
|
||||
filemenu = Menu(menubar, tearoff=0)
|
||||
filemenu.add_command(label="Create Shortcut", command=start)
|
||||
filemenu.add_command(label="Disable Dark Mode", command=toggle_theme)
|
||||
menubar.add_cascade(label="File", menu=filemenu)
|
||||
|
||||
debug_menu = Menu(menubar, tearoff=0)
|
||||
debug_menu.add_command(label="Check PixelVal", command=start)
|
||||
debug_menu.add_command(label="Log Dump", command=start)
|
||||
menubar.add_cascade(label="Debug", menu=debug_menu)
|
||||
root.config(menu=menubar)
|
||||
# endregion
|
||||
|
||||
# region console
|
||||
console = Text(root, state='disabled', wrap='none', background="#707070", fg="#ffffff")
|
||||
console.pack(fill=BOTH, expand=True, pady=(15, 15), padx=(5, 5))
|
||||
console.mark_set("sentinel", INSERT)
|
||||
console.config(state=DISABLED)
|
||||
|
||||
controls_frame = Frame(root)
|
||||
# endregion
|
||||
|
||||
# region controls
|
||||
left_frame = Frame(controls_frame)
|
||||
|
||||
Label(left_frame, text="IP").grid(row=0, column=0)
|
||||
ip = Entry(left_frame)
|
||||
ip.grid(row=0, column=1)
|
||||
|
||||
Label(left_frame, text="Fullscreen: ").grid(row=1, column=0, pady=(5, 5))
|
||||
borderless = Checkbutton(left_frame)
|
||||
borderless.grid(row=1, column=1)
|
||||
|
||||
left_frame.grid(row=0, column=0)
|
||||
|
||||
right_frame = Frame(controls_frame)
|
||||
|
||||
Label(right_frame, text="Action Key:").grid(row=0, column=0)
|
||||
action_key_entry = Entry(right_frame)
|
||||
action_key_entry.grid(row=0, column=1)
|
||||
action_key_entry.insert(0, "e")
|
||||
|
||||
Label(right_frame, text="Press start").grid(row=1, columnspan=2, pady=(5, 5))
|
||||
|
||||
right_frame.grid(row=0, column=1, padx=(50, 0))
|
||||
|
||||
controls_frame.pack()
|
||||
Button(root, text="START", width=25, command=start).pack(pady=(15, 15))
|
||||
# endregion
|
||||
|
||||
apply_theme(dark_mode)
|
||||
root.update()
|
||||
root.minsize(root.winfo_width(), root.winfo_height())
|
||||
root.mainloop()
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -1,63 +0,0 @@
|
||||
from fishy.systems.controls import Control
|
||||
|
||||
|
||||
class Log:
|
||||
"""
|
||||
Simple logging script
|
||||
"""
|
||||
ouUsed = False
|
||||
prevOuUsed = False
|
||||
printIds = []
|
||||
|
||||
@staticmethod
|
||||
def Loop():
|
||||
"""
|
||||
Method to be called in the start of the main loop
|
||||
"""
|
||||
Log.ouUsed = False
|
||||
|
||||
@staticmethod
|
||||
def LoopEnd():
|
||||
"""
|
||||
method to be called in the end of the main loop
|
||||
"""
|
||||
if Log.prevOuUsed and not Log.ouUsed:
|
||||
Log.ctrl()
|
||||
Log.prevOuUsed = Log.ouUsed
|
||||
|
||||
@staticmethod
|
||||
def ctrl():
|
||||
"""
|
||||
Logs the control manual for the current control state
|
||||
"""
|
||||
print(Control.getControlHelp())
|
||||
|
||||
@staticmethod
|
||||
def ou(s):
|
||||
"""
|
||||
Logging output which is supposed to dumps a lot of data,
|
||||
so that after it ends, controls help is printed again
|
||||
:param s: string to log
|
||||
"""
|
||||
Log.ouUsed = True
|
||||
print(s)
|
||||
|
||||
@staticmethod
|
||||
def po(i, s):
|
||||
"""
|
||||
print once
|
||||
logs the string passed only once event if it is called multiple times
|
||||
:param i: unique integer
|
||||
:param s: string to log
|
||||
"""
|
||||
if i not in Log.printIds:
|
||||
print(s)
|
||||
Log.printIds.append(i)
|
||||
|
||||
@staticmethod
|
||||
def clearPrintIds():
|
||||
"""
|
||||
clears print id for print once, so that it is printed again
|
||||
"""
|
||||
Log.printIds = []
|
||||
|
Loading…
Reference in New Issue
Block a user