Загрузка данных
import keyboard
import time
import threading
import pyautogui
from pynput.mouse import Controller, Button
from pynput.keyboard import Key, Controller as KeyboardController
import json
import os
import traceback
import sys
try:
import win32api
import win32con
DIRECT_INPUT = True
except ImportError:
DIRECT_INPUT = False
print("Предупреждение: win32api не установлен.")
class ParkourBot:
def __init__(self):
self.running = False
self.paused = False
self.block_found = False
self.current_pitch = 0
self.min_pitch = 15
self.step_down = 2
self.scan_speed = 10
self.mouse = Controller()
self.keyboard_controller = KeyboardController()
# Расширенные настройки времени
self.timings = {
# Прыжок
'jump_delay': 0.1, # Задержка перед прыжком
'jump_hold': 0.15, # Длительность удержания пробела
'double_jump_delay': 0.05, # Задержка между двойными прыжками
# Движение
'forward_time': 0.3, # Время движения вперёд
'acceleration_time': 0.15, # Время разгона перед прыжком
'post_jump_forward': 0.2, # Движение вперёд после прыжка
# Камера
'camera_reset_delay': 0.2, # Задержка выпрямления камеры
'camera_up_angle': 5, # На сколько поднимать камеру перед прыжком (пиксели)
'camera_up_delay': 0.1, # Задержка подъёма камеры
# Стабилизация
'landing_delay': 0.5, # Задержка после приземления
'stabilization_time': 0.1, # Время стабилизации
# Сканирование
'block_check_delay': 0.05, # Задержка между проверками
'scan_rotation_speed': 0.02, # Скорость вращения
'scan_angle_step': 10, # Шаг угла сканирования
# Паузы
'resume_delay': 0.3, # Задержка перед возобновлением
}
# Состояние клавиш
self.keys_pressed = {
'w': False,
'space': False
}
# Цвета блоков
self.block_colors = [
(143, 58, 47),
(178, 74, 58),
(150, 60, 50),
(170, 70, 55),
(160, 65, 52),
(185, 80, 60),
(140, 55, 45),
(190, 75, 62),
]
self.load_settings()
def release_all_keys(self):
"""Освобождает все зажатые клавиши"""
try:
if self.keys_pressed['w']:
keyboard.release('w')
self.keys_pressed['w'] = False
if self.keys_pressed['space']:
keyboard.release('space')
self.keys_pressed['space'] = False
except:
pass
def load_settings(self):
"""Загружает настройки из файла"""
try:
if os.path.exists('parkour_settings.json'):
with open('parkour_settings.json', 'r', encoding='utf-8') as f:
saved_timings = json.load(f)
self.timings.update(saved_timings)
print("✓ Предыдущие настройки загружены")
return True
except Exception as e:
print(f"⚠ Не удалось загрузить настройки: {e}")
return False
def save_settings(self):
"""Сохраняет настройки в файл"""
try:
with open('parkour_settings.json', 'w', encoding='utf-8') as f:
json.dump(self.timings, f, indent=4, ensure_ascii=False)
print("✓ Настройки сохранены")
return True
except Exception as e:
print(f"⚠ Не удалось сохранить настройки: {e}")
return False
def configure_timings(self):
"""Расширенная настройка времени"""
try:
print("\n" + "="*60)
print("НАСТРОЙКА ПАРАМЕТРОВ БОТА")
print("="*60)
# Проверяем, есть ли сохранённые настройки
has_saved = os.path.exists('parkour_settings.json')
if has_saved:
print("\nНайдены сохранённые настройки!")
use_saved = input("Использовать сохранённые настройки? (Y/n): ").strip().lower()
if use_saved != 'n':
print("✓ Используются сохранённые настройки")
self.show_current_settings()
return
print("\nВведите значения (Enter - оставить текущее, 0 - сбросить на стандартное)")
print("="*60)
# Группы настроек
settings_groups = {
"НАСТРОЙКИ ПРЫЖКА": [
('jump_delay', 'Задержка перед прыжком', 0.05, 0.5, 'сек'),
('jump_hold', 'Длительность удержания пробела', 0.05, 0.5, 'сек'),
('double_jump_delay', 'Задержка между двойными прыжками', 0.01, 0.2, 'сек'),
],
"НАСТРОЙКИ ДВИЖЕНИЯ": [
('forward_time', 'Время движения вперёд', 0.1, 1.0, 'сек'),
('acceleration_time', 'Время разгона перед прыжком', 0.05, 0.5, 'сек'),
('post_jump_forward', 'Движение вперёд после прыжка', 0.1, 0.5, 'сек'),
],
"НАСТРОЙКИ КАМЕРЫ": [
('camera_reset_delay', 'Скорость выпрямления камеры', 0.05, 0.5, 'сек'),
('camera_up_angle', 'Подъём камеры перед прыжком', 0, 20, 'пикселей'),
('camera_up_delay', 'Задержка подъёма камеры', 0.05, 0.3, 'сек'),
],
"СТАБИЛИЗАЦИЯ": [
('landing_delay', 'Ожидание приземления', 0.1, 1.0, 'сек'),
('stabilization_time', 'Время стабилизации', 0.05, 0.5, 'сек'),
('resume_delay', 'Задержка перед продолжением', 0.1, 1.0, 'сек'),
],
"СКАНИРОВАНИЕ": [
('block_check_delay', 'Задержка между проверками', 0.01, 0.2, 'сек'),
('scan_rotation_speed', 'Скорость вращения', 0.01, 0.1, 'сек'),
('scan_angle_step', 'Шаг угла сканирования', 5, 30, 'градусов'),
]
}
# Стандартные значения для сброса
default_timings = self.timings.copy()
for group_name, settings in settings_groups.items():
print(f"\n{'─'*40}")
print(f"▶ {group_name}")
print('─'*40)
for setting_key, description, min_val, max_val, unit in settings:
current = self.timings[setting_key]
print(f"\n {description}")
print(f" Текущее: {current} {unit} (от {min_val} до {max_val})")
user_input = input(" Новое значение: ").strip()
if user_input == "":
print(f" ✓ Оставлено: {current} {unit}")
elif user_input == "0":
self.timings[setting_key] = default_timings[setting_key]
print(f" ✓ Сброшено на: {default_timings[setting_key]} {unit}")
else:
try:
new_value = float(user_input)
if min_val <= new_value <= max_val:
self.timings[setting_key] = new_value
print(f" ✓ Установлено: {new_value} {unit}")
else:
print(f" ⚠ Значение должно быть от {min_val} до {max_val}")
except ValueError:
print(" ⚠ Введите число!")
self.save_settings()
# Тестовый прыжок
print("\n" + "="*60)
print("ТЕСТОВЫЙ ПРЫЖОК")
print("="*60)
print("\nПереключитесь на Minecraft для теста!")
for i in range(3, 0, -1):
print(f" {i}...")
time.sleep(1)
# Тест с подъёмом камеры
print(" Поднимаю камеру...")
self.move_mouse_relative(0, -self.timings['camera_up_angle'])
time.sleep(self.timings['camera_up_delay'])
print(" Прыжок!")
keyboard.press('space')
time.sleep(self.timings['jump_hold'])
keyboard.release('space')
# Возвращаем камеру
self.move_mouse_relative(0, self.timings['camera_up_angle'])
time.sleep(0.5)
print("✓ Тест завершён")
print("="*60)
except Exception as e:
print(f"⚠ Ошибка при настройке: {e}")
traceback.print_exc()
def show_current_settings(self):
"""Показывает текущие настройки"""
print("\n" + "="*50)
print("ТЕКУЩИЕ НАСТРОЙКИ:")
print("="*50)
for key, value in self.timings.items():
print(f" {key}: {value}")
print("="*50)
def move_mouse_relative(self, dx, dy):
"""Безопасное движение мыши"""
try:
if DIRECT_INPUT:
win32api.mouse_event(win32con.MOUSEEVENTF_MOVE, int(dx), int(dy), 0, 0)
else:
current_pos = self.mouse.position
self.mouse.position = (current_pos[0] + dx, current_pos[1] + dy)
except:
pass
def find_block(self):
"""Поиск блока на экране"""
try:
screenshot = pyautogui.screenshot()
width, height = screenshot.size
center_x = width // 2
center_y = height // 2
pixel = screenshot.getpixel((center_x, center_y))
for block_color in self.block_colors:
if self.color_similar(pixel, block_color, 25):
return True, (center_x, center_y)
return False, None
except:
return False, None
def color_similar(self, color1, color2, tolerance):
"""Сравнение цветов"""
try:
return (abs(color1[0] - color2[0]) < tolerance and
abs(color1[1] - color2[1]) < tolerance and
abs(color1[2] - color2[2]) < tolerance)
except:
return False
def raise_camera_for_jump(self):
"""Поднимает камеру перед прыжком"""
try:
if self.timings['camera_up_angle'] > 0:
print(f" Подъём камеры на {self.timings['camera_up_angle']} пикселей")
self.move_mouse_relative(0, -self.timings['camera_up_angle'])
time.sleep(self.timings['camera_up_delay'])
except Exception as e:
print(f" ⚠ Ошибка подъёма камеры: {e}")
def lower_camera_after_jump(self):
"""Опускает камеру после прыжка"""
try:
if self.timings['camera_up_angle'] > 0:
self.move_mouse_relative(0, self.timings['camera_up_angle'])
time.sleep(self.timings['camera_up_delay'])
except:
pass
def reset_camera(self):
"""Выпрямление камеры"""
try:
if self.current_pitch > 0:
steps = 5
pitch_per_step = self.current_pitch / steps
for i in range(steps):
if not self.running or self.paused:
break
self.move_mouse_relative(0, -pitch_per_step)
time.sleep(self.timings['camera_reset_delay'] / steps)
self.current_pitch = 0
except:
pass
def rotate_head_horizontal(self):
"""Горизонтальное сканирование"""
try:
for rotation in range(2):
if not self.running or self.paused:
break
for i in range(0, 180, self.timings['scan_angle_step']):
if not self.running or self.paused:
break
self.move_mouse_relative(self.timings['scan_angle_step'], 0)
time.sleep(self.timings['scan_rotation_speed'])
found, block_pos = self.find_block()
if found:
return True, block_pos
return False, None
except:
return False, None
def look_down(self):
"""Опускание головы"""
try:
if self.current_pitch < self.min_pitch:
self.move_mouse_relative(0, self.step_down)
self.current_pitch += self.step_down
except:
pass
def perform_acceleration(self):
"""Разгон перед прыжком"""
try:
print(" Разгон...")
keyboard.press('w')
self.keys_pressed['w'] = True
# Постепенное ускорение
accel_steps = 5
step_time = self.timings['acceleration_time'] / accel_steps
for i in range(accel_steps):
if not self.running or self.paused:
break
time.sleep(step_time)
print(f" Разгон завершён ({self.timings['acceleration_time']} сек)")
except Exception as e:
print(f" ⚠ Ошибка разгона: {e}")
def perform_jump(self, jump_type="medium_jump"):
"""Выполнение прыжка с ускорением и подъёмом камеры"""
try:
print(f"\n{'='*30}")
print(f"ВЫПОЛНЕНИЕ ПРЫЖКА ({jump_type})")
print('='*30)
# 1. Выпрямляем камеру если нужно
self.reset_camera()
time.sleep(self.timings['jump_delay'])
# 2. Разгон
self.perform_acceleration()
# 3. Поднимаем камеру для прыжка
self.raise_camera_for_jump()
# 4. Прыжок
print(" Прыжок!")
if jump_type == "high_jump":
# Высокий прыжок с двойным нажатием
keyboard.press('space')
self.keys_pressed['space'] = True
time.sleep(self.timings['jump_hold'] * 1.3)
keyboard.release('space')
self.keys_pressed['space'] = False
time.sleep(self.timings['double_jump_delay'])
keyboard.press('space')
self.keys_pressed['space'] = True
time.sleep(self.timings['jump_hold'] * 0.7)
keyboard.release('space')
self.keys_pressed['space'] = False
elif jump_type == "medium_jump":
# Средний прыжок
keyboard.press('space')
self.keys_pressed['space'] = True
time.sleep(self.timings['jump_hold'])
keyboard.release('space')
self.keys_pressed['space'] = False
else:
# Низкий прыжок
keyboard.press('space')
self.keys_pressed['space'] = True
time.sleep(self.timings['jump_hold'] * 0.7)
keyboard.release('space')
self.keys_pressed['space'] = False
# 5. Опускаем камеру обратно
self.lower_camera_after_jump()
# 6. Движение вперёд после прыжка
time.sleep(self.timings['post_jump_forward'])
# 7. Отпускаем движение вперёд
keyboard.release('w')
self.keys_pressed['w'] = False
# 8. Приземление и стабилизация
print(" Приземление...")
time.sleep(self.timings['landing_delay'])
time.sleep(self.timings['stabilization_time'])
print("✓ Прыжок завершён")
print('='*30 + '\n')
except Exception as e:
print(f"⚠ Ошибка прыжка: {e}")
self.release_all_keys()
def parkour_cycle(self):
"""Основной цикл с поддержкой паузы"""
print("\nЗапуск цикла паркура...")
while self.running:
try:
# Проверка паузы
if self.paused:
time.sleep(0.1)
continue
# Поиск блока
found, block_pos = self.find_block()
if found:
print("✓ Блок обнаружен!")
self.perform_jump("medium_jump")
time.sleep(self.timings['resume_delay'])
else:
print("Поиск блока...")
found_in_scan, _ = self.rotate_head_horizontal()
if found_in_scan:
self.perform_jump("medium_jump")
else:
self.look_down()
if self.current_pitch >= self.min_pitch:
self.reset_camera()
time.sleep(self.timings['block_check_delay'])
except Exception as e:
print(f"Ошибка в цикле: {e}")
self.release_all_keys()
time.sleep(0.5)
def start(self):
"""Запуск бота с улучшенным управлением паузой"""
try:
# Настройка
self.configure_timings()
print("\n" + "="*60)
print("БОТ ПАРКУРА ЗАПУЩЕН!")
print("="*60)
print("\nУПРАВЛЕНИЕ:")
print(" F8 - Пауза/Продолжение")
print(" F9 - Полная остановка")
print(" F10 - Показать настройки")
print("="*60)
self.running = True
self.paused = False
# Запуск основного цикла
bot_thread = threading.Thread(target=self.parkour_cycle)
bot_thread.daemon = True
bot_thread.start()
# Обработка команд
f8_pressed = False
f10_pressed = False
while self.running:
try:
# Обработка F8 с защитой от дребезга
if keyboard.is_pressed('F8'):
if not f8_pressed:
f8_pressed = True
self.paused = not self.paused
if self.paused:
print("\n⏸ ПАУЗА")
self.release_all_keys()
else:
print("\n▶ ПРОДОЛЖЕНИЕ")
time.sleep(self.timings['resume_delay'])
else:
f8_pressed = False
# Обработка F10
if keyboard.is_pressed('F10'):
if not f10_pressed:
f10_pressed = True
was_paused = self.paused
self.paused = True
self.show_current_settings()
self.paused = was_paused
else:
f10_pressed = False
# Остановка
if keyboard.is_pressed('F9'):
self.r