-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
149 lines (118 loc) · 4.41 KB
/
Copy pathmain.py
File metadata and controls
149 lines (118 loc) · 4.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"""
Broken Blade Bot - Master Execution Loop
==========================================
Two-Layer Architecture
Layer 1 StateController (Brain) - dedicated 60 FPS thread
Layer 2 Action handlers (Muscle) - dispatched from this 30 Hz main loop
Hotkeys:
F1 = pause / resume
Esc = quit cleanly
Usage:
python main.py
"""
import sys
import time
import threading
from pynput import keyboard
from core.screen import ScreenGrabber
from core.input import InputEmulator
from core.state import StateController, GameState
from handlers.combat import CombatEngine
from handlers.exploration import ExplorationManager
from handlers.loot import LootHandler
MAIN_HZ = 30 # handler dispatch rate (StateController runs independently at 60 Hz)
# -- Global control flags ------------------------------------------------------
_active = False
_quit = False
_lock = threading.Lock()
def _on_press(key) -> bool | None:
global _active, _quit
if key == keyboard.Key.f1:
with _lock:
_active = not _active
print(f"\n[Bot] {'[PLAY] ACTIVE' if _active else '[PAUSE] PAUSED'}")
elif key == keyboard.Key.esc:
with _lock:
_quit = True
print("\n[Bot] Shutting down ...")
return False # stop pynput listener
return None
# -- Entry point ---------------------------------------------------------------
def main() -> None:
print("=" * 52)
print(" Broken Blade Bot | Two-Layer Architecture")
print(" F1 = start/pause Esc = quit")
print("=" * 52)
# -- Subsystem init --------------------------------------------------------
grabber = ScreenGrabber(monitor_idx=2, target_fps=60)
input_emu = InputEmulator()
state_ctl = StateController(grabber)
combat = CombatEngine(grabber, input_emu)
explore = ExplorationManager(input_emu, state_ctl)
loot = LootHandler(input_emu)
handlers = {
GameState.EXPLORING: explore, # holds W+Ctrl toward boss, taps G to lock
GameState.ENGAGING: explore,
GameState.COMBAT: combat,
GameState.LOOTING: loot,
}
# -- Start background threads -----------------------------------------------
grabber.start()
state_ctl.start()
kb = keyboard.Listener(on_press=_on_press)
kb.start()
print("[Bot] Ready.\n")
# -- Main dispatch loop -----------------------------------------------------
interval = 1.0 / MAIN_HZ
prev_state: GameState | None = None
try:
while True:
with _lock:
should_quit = _quit
should_active = _active
if should_quit:
break
if not should_active:
time.sleep(0.05)
continue
t0 = time.perf_counter()
state = state_ctl.state
# -- State transition -----------------------------------------------
if state != prev_state:
# on_exit for old state
if prev_state is not None and prev_state in handlers:
try:
handlers[prev_state].on_exit()
except Exception as exc:
print(f"[Bot] on_exit error ({prev_state.name}): {exc}")
# on_enter for new state
if state in handlers:
try:
handlers[state].on_enter()
except Exception as exc:
print(f"[Bot] on_enter error ({state.name}): {exc}")
print(f"[Bot] -- {state.name}")
prev_state = state
# -- Dispatch tick --------------------------------------------------
try:
if state == GameState.ENGAGING:
explore.tick_engaging()
elif state in handlers:
handlers[state].tick()
except Exception as exc:
print(f"[Bot] tick error ({state.name}): {exc}")
# -- Rate limiting --------------------------------------------------
wait = interval - (time.perf_counter() - t0)
if wait > 0:
time.sleep(wait)
except KeyboardInterrupt:
pass
finally:
print("[Bot] Releasing inputs ...")
input_emu.release_all()
state_ctl.stop()
grabber.stop()
kb.stop()
print("[Bot] Stopped cleanly.")
if __name__ == "__main__":
main()