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


import keyboard
import time
import threading
import pyautogui
from pynput.mouse import Controller, Button
from pynput.keyboard import Key, Controller as KeyboardController
import random

# Библиотека для DirectInput (более низкоуровневый доступ)
try:
    import win32api
    import win32con
    DIRECT_INPUT = True
except ImportError:
    DIRECT_INPUT = False
    print("Предупреждение: win32api не установлен. Будет использован pynput.")

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.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),
        ]
        
    def move_mouse_relative(self, dx, dy, use_direct_input=True):
        """Двигает мышь разными методами для совместимости с Minecraft"""
        try:
            if DIRECT_INPUT and use_direct_input:
                # Метод через Win32 API (работает с DirectInput)
                win32api.mouse_event(win32con.MOUSEEVENTF_MOVE, int(dx), int(dy), 0, 0)
            else:
                # Метод через pynput
                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
            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 press_key(self, key, duration=0.1):
        """Нажимает клавишу с удержанием"""
        try:
            keyboard.press(key)
            time.sleep(duration)
            keyboard.release(key)
        except:
            # Запасной метод
            if key == 'w':
                self.keyboard_controller.press('w')
                time.sleep(duration)
                self.keyboard_controller.release('w')
            elif key == 'space':
                self.keyboard_controller.press(Key.space)
                time.sleep(duration)
                self.keyboard_controller.release(Key.space)
    
    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(0.02)
                
                # Проверяем блок
                found, block_pos = self.find_block()
                if found:
                    print(f"Блок найден при сканировании!")
                    return True
        
        return False
    
    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 reset_head_position(self):
        """Возвращает голову в исходное положение"""
        if self.current_pitch > 0:
            self.move_mouse_relative(0, -self.current_pitch)
            self.current_pitch = 0
            print("Голова возвращена")
    
    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}")
        
        # Начинаем движение вперед
        keyboard.press('w')
        time.sleep(0.05)
        
        if jump_type == "high_jump":
            # Высокий прыжок
            keyboard.press('space')
            time.sleep(0.2)
            keyboard.release('space')
            time.sleep(0.05)
            # Второй прыжок для дальности
            keyboard.press('space')
            time.sleep(0.1)
            keyboard.release('space')
            
        elif jump_type == "medium_jump":
            # Средний прыжок
            keyboard.press('space')
            time.sleep(0.15)
            keyboard.release('space')
            
        else:
            # Низкий прыжок
            keyboard.press('space')
            time.sleep(0.08)
            keyboard.release('space')
        
        # Продолжаем движение
        time.sleep(0.2)
        keyboard.release('w')
        time.sleep(0.1)
    
    def parkour_cycle(self):
        """Основной цикл"""
        print("Запуск паркура...")
        
        while self.running:
            try:
                found, block_pos = self.find_block()
                
                if found:
                    print("Блок найден!")
                    jump_type = self.calculate_jump(block_pos)
                    self.perform_jump(jump_type)
                    time.sleep(0.2)
                    
                else:
                    print("Ищу блок...")
                    if not self.rotate_head_horizontal():
                        self.look_down()
                        if self.current_pitch >= self.min_pitch:
                            self.reset_head_position()
                    else:
                        found_again, block_pos = self.find_block()
                        if found_again:
                            jump_type = self.calculate_jump(block_pos)
                            self.perform_jump(jump_type)
                            self.reset_head_position()
                    
                    time.sleep(0.05)
                    
            except Exception as e:
                print(f"Ошибка: {e}")
                time.sleep(0.1)
    
    def start(self):
        """Запуск бота"""
        self.running = True
        print("=" * 50)
        print("БОТ ПАРКУРА ЗАПУЩЕН!")
        print("=" * 50)
        print("F8 - Пауза")
        print("F9 - Стоп")
        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("Бот остановлен!")
                break
            elif keyboard.is_pressed('F8'):
                self.running = not self.running
                state = "ПРОДОЛЖЕН" if self.running else "ПАУЗА"
                print(f"Статус: {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")
    print("=" * 50)
    print("\nВАЖНО:")
    print("1. Чувствительность мыши в игре = 0%")
    print("2. Запустите от имени администратора")
    print("3. Игра в оконном режиме")
    print("\nЦвета блоков: красные оттенки")
    print("=" * 50)
    
    bot = ParkourBot()
    
    print("\nЗапуск через 3 секунды...")
    for i in range(3, 0, -1):
        print(f"{i}...")
        time.sleep(1)
    
    print("СТАРТ!")
    bot.start()