Загрузка данных


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

try:
    import win32api
    import win32con
    DIRECT_INPUT = True
except ImportError:
    DIRECT_INPUT = False
    print("Предупреждение: win32api не установлен.")

class ParkourBot:
    def __init__(self):
        self.running = 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,          # Длительность удержания пробела
            'forward_time': 0.3,        # Время движения вперёд
            'landing_delay': 0.5,       # Задержка после приземления
            'camera_reset_delay': 0.2,  # Задержка выпрямления камеры
            'block_check_delay': 0.05,  # Задержка между проверками
            'scan_rotation_speed': 0.02 # Скорость вращения при сканировании
        }
        
        # Цвета блоков (красные оттенки)
        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 load_settings(self):
        """Загружает настройки из файла"""
        if os.path.exists('parkour_settings.json'):
            try:
                with open('parkour_settings.json', 'r') as f:
                    saved_timings = json.load(f)
                    self.timings.update(saved_timings)
                    print("Настройки загружены из файла")
            except:
                print("Не удалось загрузить настройки, используются стандартные")
    
    def save_settings(self):
        """Сохраняет настройки в файл"""
        with open('parkour_settings.json', 'w') as f:
            json.dump(self.timings, f, indent=4)
            print("Настройки сохранены")
    
    def configure_timings(self):
        """Настройка времени перед запуском"""
        print("\n" + "="*50)
        print("НАСТРОЙКА ВРЕМЕНИ ДЕЙСТВИЙ")
        print("="*50)
        print("\nВведите значения в секундах (можно десятичные)")
        print("Нажмите Enter чтобы оставить текущее значение\n")
        
        settings = [
            ('jump_delay', 'Задержка перед прыжком (после обнаружения блока)', 0.05, 0.5),
            ('jump_hold', 'Длительность удержания пробела (высота прыжка)', 0.05, 0.5),
            ('forward_time', 'Время движения вперёд во время прыжка', 0.1, 1.0),
            ('landing_delay', 'Задержка после приземления (для стабилизации)', 0.1, 1.0),
            ('camera_reset_delay', 'Задержка выпрямления камеры', 0.05, 0.5),
            ('block_check_delay', 'Задержка между проверками блоков', 0.01, 0.2),
            ('scan_rotation_speed', 'Скорость вращения при сканировании', 0.01, 0.1)
        ]
        
        for setting_key, description, min_val, max_val in settings:
            current = self.timings[setting_key]
            print(f"\n{description}")
            print(f"Текущее значение: {current} сек (мин: {min_val}, макс: {max_val})")
            
            while True:
                user_input = input("Новое значение: ").strip()
                
                if user_input == "":
                    print(f"Оставлено: {current} сек")
                    break
                
                try:
                    new_value = float(user_input)
                    if min_val <= new_value <= max_val:
                        self.timings[setting_key] = new_value
                        print(f"Установлено: {new_value} сек")
                        break
                    else:
                        print(f"Значение должно быть от {min_val} до {max_val}")
                except ValueError:
                    print("Введите число!")
        
        self.save_settings()
        
        print("\n" + "="*50)
        print("ТЕСТИРОВАНИЕ НАСТРОЕК")
        print("="*50)
        print("\nПроверьте текущие настройки прыжка:")
        print("Будет выполнен тестовый прыжок на месте")
        print("Переключитесь на Minecraft!")
        
        for i in range(3, 0, -1):
            print(f"{i}...")
            time.sleep(1)
        
        # Тестовый прыжок
        print("Тестовый прыжок!")
        keyboard.press('space')
        time.sleep(self.timings['jump_hold'])
        keyboard.release('space')
        time.sleep(0.5)
        
        print("\nНастройки применены!")
        print("Если нужно изменить - перезапустите программу")
        print("="*50)
    
    def move_mouse_relative(self, dx, dy, use_direct_input=True):
        """Двигает мышь"""
        try:
            if DIRECT_INPUT and use_direct_input:
                win32api.mouse_event(win32con.MOUSEEVENTF_MOVE, int(dx), int(dy), 0, 0)
            else:
                current_pos = self.mouse.position
                new_x = current_pos[0] + dx
                new_y = current_pos[1] + dy
                self.mouse.position = (new_x, new_y)
        except Exception as e:
            print(f"Ошибка движения мыши: {e}")
            pyautogui.moveRel(dx, dy, duration=0.01)
    
    def find_block(self):
        """Ищет блок на экране"""
        try:
            screenshot = pyautogui.screenshot()
            width, height = screenshot.size
            
            center_x = width // 2
            center_y = height // 2
            search_radius = 60
            
            # Проверяем центр
            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)
            
            # Сканируем область
            for y in range(center_y - search_radius, center_y + search_radius, 10):
                for x in range(center_x - search_radius, center_x + search_radius, 10):
                    try:
                        pixel = screenshot.getpixel((x, y))
                        for block_color in self.block_colors:
                            if self.color_similar(pixel, block_color, 25):
                                return True, (x, y)
                    except:
                        continue
            
            return False, None
        except Exception as e:
            print(f"Ошибка поиска: {e}")
            return False, None
    
    def color_similar(self, color1, color2, tolerance):
        return (abs(color1[0] - color2[0]) < tolerance and
                abs(color1[1] - color2[1]) < tolerance and
                abs(color1[2] - color2[2]) < tolerance)
    
    def reset_camera(self):
        """Выпрямляет камеру в горизонтальное положение"""
        if self.current_pitch > 0:
            print(f"Выпрямляю камеру (был наклон {self.current_pitch})")
            # Плавно возвращаем камеру
            steps = 5
            pitch_per_step = self.current_pitch / steps
            
            for i in range(steps):
                self.move_mouse_relative(0, -pitch_per_step)
                time.sleep(self.timings['camera_reset_delay'] / steps)
            
            self.current_pitch = 0
    
    def rotate_head_horizontal(self):
        """Сканирует горизонтально"""
        print("Сканирую...")
        
        for rotation in range(3):
            if not self.running:
                break
            
            for i in range(0, 180, self.scan_speed):
                if not self.running:
                    break
                
                self.move_mouse_relative(self.scan_speed, 0)
                time.sleep(self.timings['scan_rotation_speed'])
                
                found, block_pos = self.find_block()
                if found:
                    print("Блок найден!")
                    return True, block_pos
        
        return False, None
    
    def look_down(self):
        """Опускает голову"""
        if self.current_pitch < self.min_pitch:
            self.move_mouse_relative(0, self.step_down)
            self.current_pitch += self.step_down
            print(f"Наклон: {self.current_pitch}")
    
    def calculate_jump(self, block_pos):
        """Определяет тип прыжка по высоте блока"""
        screen_center_y = pyautogui.size()[1] // 2
        block_y = block_pos[1]
        height_diff = screen_center_y - block_y
        
        if height_diff > 80:
            return "high_jump"
        elif height_diff > 30:
            return "medium_jump"
        else:
            return "low_jump"
    
    def perform_jump(self, jump_type):
        """Выполняет прыжок с выпрямлением камеры"""
        print(f"Подготовка к прыжку типа: {jump_type}")
        
        # 1. Сначала выпрямляем камеру
        self.reset_camera()
        time.sleep(self.timings['jump_delay'])
        
        # 2. Начинаем движение вперёд с ускорением
        print("Движение вперёд...")
        keyboard.press('w')
        
        # Небольшой разгон
        time.sleep(0.05)
        
        # 3. Выполняем прыжок в зависимости от типа
        print("Прыжок!")
        if jump_type == "high_jump":
            # Высокий прыжок с удержанием
            keyboard.press('space')
            time.sleep(self.timings['jump_hold'] * 1.3)  # Дольше для высоты
            keyboard.release('space')
            time.sleep(0.05)
            # Двойной прыжок для дальности
            keyboard.press('space')
            time.sleep(self.timings['jump_hold'] * 0.7)
            keyboard.release('space')
            
        elif jump_type == "medium_jump":
            # Средний прыжок
            keyboard.press('space')
            time.sleep(self.timings['jump_hold'])
            keyboard.release('space')
            
        else:
            # Низкий прыжок (короткий)
            keyboard.press('space')
            time.sleep(self.timings['jump_hold'] * 0.7)
            keyboard.release('space')
        
        # 4. Продолжаем движение вперёд после прыжка
        print("Полёт...")
        time.sleep(self.timings['forward_time'])
        
        # 5. Отпускаем движение вперёд
        keyboard.release('w')
        
        # 6. Ждём приземления (для стабилизации)
        print("Приземление...")
        time.sleep(self.timings['landing_delay'])
        
        # 7. Проверяем что мы стоим на месте
        print("Прыжок завершён, стабилизация")
        time.sleep(0.1)
    
    def parkour_cycle(self):
        """Основной цикл паркура"""
        print("Запуск цикла паркура...")
        print(f"Настройки времени: {self.timings}")
        
        while self.running:
            try:
                # Проверяем наличие блока
                found, block_pos = self.find_block()
                
                if found:
                    print(f"Блок найден! Координаты: {block_pos}")
                    
                    # Определяем тип прыжка
                    jump_type = self.calculate_jump(block_pos)
                    print(f"Тип прыжка: {jump_type}")
                    
                    # Выполняем прыжок (включает выпрямление камеры)
                    self.perform_jump(jump_type)
                    print("Ожидание следующего блока...\n")
                    
                else:
                    print("Блок не найден, начинаю сканирование...")
                    
                    # Ищем блок вращением
                    found_in_scan, block_pos = self.rotate_head_horizontal()
                    
                    if found_in_scan:
                        # Нашли блок при сканировании
                        jump_type = self.calculate_jump(block_pos)
                        self.perform_jump(jump_type)
                    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}")
                time.sleep(0.1)
    
    def start(self):
        """Запуск бота"""
        # Сначала настройка времени
        self.configure_timings()
        
        self.running = True
        print("\n" + "=" * 50)
        print("БОТ ПАРКУРА ЗАПУЩЕН!")
        print("=" * 50)
        print("\nУправление:")
        print("  F8 - Пауза/Продолжение")
        print("  F9 - Полная остановка")
        print("\nТекущие настройки:")
        for key, value in self.timings.items():
            print(f"  {key}: {value} сек")
        print("=" * 50)
        
        # Запуск в отдельном потоке
        bot_thread = threading.Thread(target=self.parkour_cycle)
        bot_thread.daemon = True
        bot_thread.start()
        
        # Ожидание команд
        while True:
            if keyboard.is_pressed('F9'):
                self.running = False
                print("\nБот остановлен!")
                break
            elif keyboard.is_pressed('F8'):
                self.running = not self.running
                state = "ПРОДОЛЖЕН" if self.running else "ПАУЗА"
                print(f"\nСтатус: {state}")
                time.sleep(0.5)
            
            time.sleep(0.1)

if __name__ == "__main__":
    # Проверка и установка библиотек
    import subprocess
    import sys
    
    def install_package(package):
        subprocess.check_call([sys.executable, "-m", "pip", "install", package])
    
    required_packages = ['pyautogui', 'keyboard', 'pillow', 'pynput', 'pywin32']
    
    for package in required_packages:
        try:
            __import__(package.replace('-', '_'))
        except ImportError:
            print(f"Устанавливаю {package}...")
            install_package(package)
    
    print("\n" + "=" * 50)
    print("БОТ ПАРКУРА MINECRAFT v2.0")
    print("=" * 50)
    print("\nВАЖНЫЕ ТРЕБОВАНИЯ:")
    print("1. Запуск от имени АДМИНИСТРАТОРА")
    print("2. Чувствительность мыши в игре = 0%")
    print("3. FOV = 90")
    print("4. Игра в ОКОННОМ режиме")
    print("5. Стойте прямо перед запуском")
    print("\nЦвета блоков: красные оттенки")
    print("=" * 50)
    
    input("\nНажмите Enter для начала настройки...")
    
    bot = ParkourBot()
    bot.start()