Загрузка данных
import keyboard
import time
import threading
import pyautogui
from pynput.mouse import Controller
import json
import os
import traceback
import colorsys
try:
import win32api
import win32con
DIRECT_INPUT = True
except ImportError:
DIRECT_INPUT = False
class ParkourBot:
def __init__(self):
self.running = False
self.paused = False
self.current_pitch = 0
self.mouse = Controller()
self.timings = {
# Задержка перед запуском
'start_delay': 5, # Задержка перед стартом (сек)
# Начальная позиция (смотрит вниз)
'initial_look_down': 40,
# Подъём головы (только подъём, не опускание)
'head_raise_angle': 40,
'head_raise_delay': 0.1,
# Поиск блока (вращение)
'scan_rotation_speed': 0.02,
'scan_angle_step': 10,
# Прыжок
'camera_up_angle': 30,
'camera_up_delay': 0.05,
'first_w_time': 0.08,
'w_gap': 0.03,
'second_w_time': 0.05,
'jump_hold': 0.1,
'post_jump_forward': 0.15,
# Шифт после прыжка
'shift_delay': 0.2,
'shift_hold': 0.3,
# Центрирование на блоке
'center_look_down': 40,
'center_move_speed': 0.1,
'center_move_repeat': 3,
# Приземление
'landing_delay': 0.3,
'stabilization_time': 0.1,
# Паузы
'resume_delay': 0.3,
'color_tolerance': 15,
}
self.base_colors = [
(255, 23, 23),
(255, 29, 30),
(188, 17, 18),
(196, 17, 18),
]
self.generate_color_palette()
self.settings_file = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
'parkour_settings.json'
)
self.load_settings()
def generate_color_palette(self):
self.block_colors = []
for base in self.base_colors:
self.block_colors.append(base)
r, g, b = base
h, s, v = colorsys.rgb_to_hsv(r/255, g/255, b/255)
for brightness in [0.8, 0.9, 1.1, 1.2]:
new_v = min(1.0, max(0.0, v * brightness))
new_r, new_g, new_b = colorsys.hsv_to_rgb(h, s, new_v)
color = (int(new_r * 255), int(new_g * 255), int(new_b * 255))
if color not in self.block_colors:
self.block_colors.append(color)
for saturation in [0.8, 0.9, 1.1, 1.2]:
new_s = min(1.0, max(0.0, s * saturation))
new_r, new_g, new_b = colorsys.hsv_to_rgb(h, new_s, v)
color = (int(new_r * 255), int(new_g * 255), int(new_b * 255))
if color not in self.block_colors:
self.block_colors.append(color)
print("Сгенерировано оттенков красного: " + str(len(self.block_colors)))
def load_settings(self):
try:
if os.path.exists(self.settings_file):
with open(self.settings_file, 'r', encoding='utf-8') as f:
saved = json.load(f)
for key in self.timings:
if key in saved:
self.timings[key] = saved[key]
if 'base_colors' in saved:
self.base_colors = [tuple(c) for c in saved['base_colors']]
self.generate_color_palette()
print("Настройки загружены")
except Exception as e:
print("Стандартные настройки: " + str(e))
def save_settings(self):
try:
save_data = {}
for key, value in self.timings.items():
save_data[key] = value
save_data['base_colors'] = self.base_colors
try:
with open(self.settings_file, 'w', encoding='utf-8') as f:
json.dump(save_data, f, indent=4, ensure_ascii=False)
print("Настройки сохранены")
except PermissionError:
home_dir = os.path.expanduser('~')
backup_file = os.path.join(home_dir, 'parkour_settings.json')
with open(backup_file, 'w', encoding='utf-8') as f:
json.dump(save_data, f, indent=4, ensure_ascii=False)
print("Настройки сохранены в " + backup_file)
except Exception as e:
print("Ошибка сохранения: " + str(e))
def release_keys(self):
try:
keyboard.release('w')
keyboard.release('a')
keyboard.release('s')
keyboard.release('d')
keyboard.release('space')
keyboard.release('shift')
except:
pass
def move_mouse(self, dx, dy):
try:
if DIRECT_INPUT:
win32api.mouse_event(win32con.MOUSEEVENTF_MOVE, int(dx), int(dy), 0, 0)
else:
pos = self.mouse.position
self.mouse.position = (pos[0] + dx, pos[1] + dy)
except:
pass
def color_match_percent(self, color1, color2):
try:
tolerance = self.timings['color_tolerance']
dr = abs(color1[0] - color2[0])
dg = abs(color1[1] - color2[1])
db = abs(color1[2] - color2[2])
max_diff = 255 * 3
actual_diff = dr + dg + db
similarity = 100 - (actual_diff / max_diff * 100)
return similarity >= (100 - tolerance)
except:
return False
def find_block(self):
"""Поиск красной точки только в центре экрана"""
try:
screenshot = pyautogui.screenshot()
w, h = screenshot.size
cx, cy = w // 2, h // 2
pixel = screenshot.getpixel((cx, cy))
for color in self.block_colors:
if self.color_match_percent(pixel[:3], color):
return True, (cx, cy)
return False, None
except:
return False, None
def look_down_initial(self):
"""Начальный наклон головы вниз"""
print(" Наклон головы вниз...")
angle = self.timings['initial_look_down']
for _ in range(5):
self.move_mouse(0, angle)
time.sleep(0.01)
self.current_pitch = angle * 5
print(" Голова опущена")
def raise_head(self):
"""ТОЛЬКО подъём головы (не опускает)"""
if self.current_pitch > 0:
print(" Подъём головы...")
angle = self.timings['head_raise_angle']
for _ in range(5):
self.move_mouse(0, -angle)
time.sleep(0.01)
self.current_pitch = max(0, self.current_pitch - angle * 5)
time.sleep(self.timings['head_raise_delay'])
print(" Голова поднята")
def rotate_scan(self):
"""Вращение для поиска блока (только при ходьбе)"""
print(" Поиск блока...")
for _ in range(3):
if not self.running or self.paused:
break
for _ in range(0, 360, self.timings['scan_angle_step']):
if not self.running or self.paused:
break
self.move_mouse(self.timings['scan_angle_step'], 0)
time.sleep(self.timings['scan_rotation_speed'])
found, pos = self.find_block()
if found:
print(" Блок найден!")
return True, pos
return False, None
def do_jump(self):
"""Прыжок"""
print("=" * 40)
print("ПРЫЖОК")
print("=" * 40)
# Поднимаем камеру
print(" Подъём камеры...")
angle = self.timings['camera_up_angle']
for _ in range(5):
self.move_mouse(0, -angle)
time.sleep(0.005)
time.sleep(self.timings['camera_up_delay'])
# Двойное W
print(" W W...")
keyboard.press('w')
time.sleep(self.timings['first_w_time'])
keyboard.release('w')
time.sleep(self.timings['w_gap'])
keyboard.press('w')
time.sleep(self.timings['second_w_time'])
# Прыжок
print(" Прыжок!")
keyboard.press('space')
time.sleep(self.timings['jump_hold'])
keyboard.release('space')
jump_time = time.time()
# Полёт
time.sleep(self.timings['post_jump_forward'])
keyboard.release('w')
# Приземление
print(" Приземление...")
time.sleep(self.timings['landing_delay'])
# Опускаем камеру
for _ in range(5):
self.move_mouse(0, angle)
time.sleep(0.005)
# Шифт
elapsed = time.time() - jump_time
shift_wait = max(0, self.timings['shift_delay'] - elapsed)
if shift_wait > 0:
time.sleep(shift_wait)
print(" Шифт!")
keyboard.press('shift')
time.sleep(self.timings['shift_hold'])
keyboard.release('shift')
time.sleep(self.timings['stabilization_time'])
print("Готово")
print("=" * 40)
def center_on_block(self):
"""Центрирование на блоке: ходит вперёд-назад и ищет блок"""
print("=" * 40)
print("ЦЕНТРИРОВАНИЕ")
print("=" * 40)
# Наклоняем голову вниз
print(" Наклон головы...")
angle = self.timings['center_look_down']
for _ in range(5):
self.move_mouse(0, angle)
time.sleep(0.01)
# Ходим вперёд-назад и ТОЛЬКО ТЕПЕРЬ ищем блок
for i in range(self.timings['center_move_repeat']):
if not self.running or self.paused:
break
print(" Вперёд (поиск блока)...")
keyboard.press('w')
# Ищем блок во время движения вперёд
start_time = time.time()
while time.time() - start_time < self.timings['center_move_speed']:
if not self.running or self.paused:
break
found, _ = self.find_block()
if found:
print(" Блок найден при центрировании!")
time.sleep(0.02)
keyboard.release('w')
time.sleep(0.05)
print(" Назад (поиск блока)...")
keyboard.press('s')
# Ищем блок во время движения назад
start_time = time.time()
while time.time() - start_time < self.timings['center_move_speed']:
if not self.running or self.paused:
break
found, _ = self.find_block()
if found:
print(" Блок найден при центрировании!")
time.sleep(0.02)
keyboard.release('s')
time.sleep(0.05)
print("Центрирование завершено")
print("=" * 40)
def main_loop(self):
"""Основной цикл"""
print("Запуск основного цикла...")
while self.running:
if self.paused:
time.sleep(0.1)
continue
try:
print("\n=== НОВЫЙ ЦИКЛ ===")
# Шаг 1: Наклоняем голову вниз (начальная позиция)
self.look_down_initial()
# Шаг 2: ТОЛЬКО поднимаем голову
self.raise_head()
# Шаг 3: Прыжок (сразу, без поиска)
self.do_jump()
# Шаг 4: Центрирование (ходит вперёд-назад и ТОЛЬКО ТЕПЕРЬ ищет блок)
self.center_on_block()
# Шаг 5: Если блок найден при центрировании - прыгаем снова
# (Цикл продолжается)
except Exception as e:
print("Ошибка: " + str(e))
self.release_keys()
time.sleep(0.5)
def setup_menu(self):
print("=" * 50)
print("НАСТРОЙКА БОТА")
print("=" * 50)
if os.path.exists(self.settings_file):
use = input("Загрузить сохранённые настройки? (Y/n): ").strip().lower()
if use == 'n':
print("Настройка заново...")
else:
print("Загружены сохранённые настройки")
self.show_settings()
return
print("Вводите значения или Enter (пропустить)")
print("Введите 0 для сброса на стандартное")
settings = {
"ЗАДЕРЖКИ": [
('start_delay', 'Задержка перед запуском', 1, 10, 'сек'),
],
"ЦВЕТА": [
('color_tolerance', 'Допуск цвета (%)', 5, 50, '%'),
],
"НАЧАЛЬНАЯ ПОЗИЦИЯ": [
('initial_look_down', 'Наклон головы вниз', 10, 200, 'пикс'),
('head_raise_angle', 'Подъём головы', 10, 200, 'пикс'),
],
"ПРЫЖОК": [
('camera_up_angle', 'Подъём камеры при прыжке', 10, 200, 'пикс'),
('first_w_time', 'Первое W', 0.03, 0.2, 'сек'),
('w_gap', 'Пауза между W', 0.01, 0.1, 'сек'),
('second_w_time', 'Второе W', 0.03, 0.2, 'сек'),
('jump_hold', 'Длительность прыжка', 0.05, 0.3, 'сек'),
('post_jump_forward', 'Полёт вперёд', 0.05, 0.5, 'сек'),
],
"ШИФТ": [
('shift_delay', 'Задержка перед шифтом (от прыжка)', 0.1, 1.0, 'сек'),
('shift_hold', 'Длительность шифта', 0.1, 0.5, 'сек'),
],
"ЦЕНТРИРОВАНИЕ": [
('center_look_down', 'Наклон головы при центрировании', 10, 200, 'пикс'),
('center_move_speed', 'Длительность шага', 0.05, 0.5, 'сек'),
('center_move_repeat', 'Повторений вперёд-назад', 1, 6, 'раз'),
],
"ПРИЗЕМЛЕНИЕ": [
('landing_delay', 'Ожидание приземления', 0.1, 0.8, 'сек'),
('stabilization_time', 'Стабилизация', 0.05, 0.3, 'сек'),
],
}
defaults = self.timings.copy()
for group, params in settings.items():
print("--- " + group + " ---")
for item in params:
key, desc, min_v, max_v, unit = item
cur = self.timings[key]
print(desc)
print("Текущее: " + str(cur) + " " + unit + " (от " + str(min_v) + " до " + str(max_v) + ")")
inp = input("> ").strip()
if inp == "":
print("Оставлено: " + str(cur) + " " + unit)
elif inp == "0":
self.timings[key] = defaults[key]
print("Сброшено: " + str(defaults[key]) + " " + unit)
else:
try:
val = float(inp)
if min_v <= val <= max_v:
self.timings[key] = val
print("Установлено: " + str(val) + " " + unit)
else:
print("Значение должно быть от " + str(min_v) + " до " + str(max_v))
except:
print("Введите число!")
self.save_settings()
print("Готово")
def show_settings(self):
print("Текущие настройки:")
print(" Задержка старта: " + str(self.timings['start_delay']) + " сек")
print(" Наклон вниз: " + str(self.timings['initial_look_down']) + " пикс")
print(" Подъём головы: " + str(self.timings['head_raise_angle']) + " пикс")
print(" Шифт через: " + str(self.timings['shift_delay']) + " сек")
print(" Центрирование: " + str(self.timings['center_move_repeat']) + " повторов")
def start(self):
self.setup_menu()
print("=" * 50)
print("БОТ ЗАПУСКАЕТСЯ...")
print("=" * 50)
# Задержка перед стартом
delay = self.timings['start_delay']
print("Задержка перед стартом: " + str(delay) + " сек")
print("Переключитесь на Minecraft и встаньте в позу (голова вниз)!")
for i in range(int(delay), 0, -1):
print(str(i) + "...")
time.sleep(1)
print("СТАРТ!")
print("=" * 50)
print("Цикл:")
print(" 1. Голова вниз (калибровка)")
print(" 2. Подъём головы")
print(" 3. Прыжок (сразу)")
print(" 4. Центрирование (поиск при ходьбе)")
print("F8 - Пауза | F9 - Стоп")
print("=" * 50)
self.running = True
self.paused = False
thread = threading.Thread(target=self.main_loop)
thread.daemon = True
thread.start()
f8_state = False
while self.running:
try:
if keyboard.is_pressed('F8'):
if not f8_state:
f8_state = True
self.paused = not self.paused
if self.paused:
print("ПАУЗА")
self.release_keys()
else:
print("ПРОДОЛЖЕНИЕ")
time.sleep(0.3)
else:
f8_state = False
if keyboard.is_pressed('F9'):
self.running = False
print("СТОП")
break
time.sleep(0.05)
except KeyboardInterrupt:
break
self.release_keys()
print("Выход")
if __name__ == "__main__":
print("=" * 50)
print("БОТ ПАРКУРА MINECRAFT")
print("=" * 50)
print("Цикл:")
print(" 1. Голова вниз (поза)")
print(" 2. Подъём головы (только вверх)")
print(" 3. Прыжок (сразу)")
print(" 4. Центрирование (поиск блока при ходьбе)")
print("=" * 50)
input("Нажмите Enter для настройки...")
bot = ParkourBot()
bot.start()