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


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.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):
        """Загружает настройки из файла"""
        try:
            if os.path.exists('parkour_settings.json'):
                with open('parkour_settings.json', 'r') as f:
                    saved_timings = json.load(f)
                    self.timings.update(saved_timings)
                    print("✓ Настройки загружены")
        except Exception as e:
            print(f"⚠ Не удалось загрузить настройки: {e}")
    
    def save_settings(self):
        """Сохраняет настройки в файл"""
        try:
            with open('parkour_settings.json', 'w') as f:
                json.dump(self.timings, f, indent=4)
            print("✓ Настройки сохранены")
        except Exception as e:
            print(f"⚠ Не удалось сохранить настройки: {e}")
    
    def configure_timings(self):
        """Настройка времени перед запуском"""
        try:
            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:
                try:
                    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("⚠ Введите число!")
                except Exception as e:
                    print(f"⚠ Ошибка при настройке {setting_key}: {e}")
                    continue
            
            self.save_settings()
            
            print("\n" + "="*50)
            print("ТЕСТОВЫЙ ПРЫЖОК")
            print("="*50)
            print("\nПереключитесь на 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("✓ Тест завершён")
            print("="*50)
            
        except Exception as e:
            print(f"⚠ Ошибка при настройке: {e}")
            traceback.print_exc()
    
    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 reset_camera(self):
        """Выпрямление камеры"""
        try:
            if self.current_pitch > 0:
                print(f"Выпрямление камеры (наклон: {self.current_pitch})")
                steps = 5
                pitch_per_step = self.current_pitch / steps
                
                for i in range(steps):
                    if not self.running:
                        break
                    self.move_mouse_relative(0, -pitch_per_step)
                    time.sleep(self.timings['camera_reset_delay'] / steps)
                
                self.current_pitch = 0
        except Exception as e:
            print(f"Ошибка выпрямления: {e}")
    
    def rotate_head_horizontal(self):
        """Горизонтальное сканирование"""
        try:
            print("Сканирование...")
            
            for rotation in range(2):  # Уменьшил до 2 оборотов
                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
        except Exception as e:
            print(f"Ошибка сканирования: {e}")
            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_jump(self, jump_type):
        """Выполнение прыжка"""
        try:
            print(f"Прыжок: {jump_type}")
            
            # Выпрямляем камеру
            self.reset_camera()
            time.sleep(self.timings['jump_delay'])
            
            # Движение вперёд
            keyboard.press('w')
            time.sleep(0.05)
            
            # Прыжок
            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')
            
            # Движение после прыжка
            time.sleep(self.timings['forward_time'])
            keyboard.release('w')
            
            # Приземление
            time.sleep(self.timings['landing_delay'])
            print("✓ Прыжок завершён")
            
        except Exception as e:
            print(f"Ошибка прыжка: {e}")
            # Гарантированно отпускаем клавиши
            try:
                keyboard.release('w')
                keyboard.release('space')
            except:
                pass
    
    def parkour_cycle(self):
        """Основной цикл"""
        print("Запуск паркура...")
        
        while self.running:
            try:
                found, block_pos = self.find_block()
                
                if found:
                    print("✓ Блок обнаружен!")
                    # Простой прыжок вперёд
                    self.perform_jump("medium_jump")
                    time.sleep(0.2)
                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}")
                traceback.print_exc()
                time.sleep(0.5)  # Пауза при ошибке
    
    def start(self):
        """Запуск бота"""
        try:
            # Настройка
            self.configure_timings()
            
            print("\n" + "="*50)
            print("БОТ ПАРКУРА ЗАПУЩЕН!")
            print("="*50)
            print("F8 - Пауза | F9 - Стоп")
            print("="*50)
            
            self.running = True
            
            # Запуск в отдельном потоке
            bot_thread = threading.Thread(target=self.parkour_cycle)
            bot_thread.daemon = True
            bot_thread.start()
            
            # Ожидание команд
            while True:
                try:
                    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)
                except KeyboardInterrupt:
                    break
                except:
                    pass
                    
        except Exception as e:
            print(f"Критическая ошибка: {e}")
            traceback.print_exc()
        finally:
            # Гарантированно отпускаем все клавиши
            try:
                keyboard.release('w')
                keyboard.release('space')
            except:
                pass
            print("Бот завершил работу")

if __name__ == "__main__":
    print("\n" + "="*50)
    print("БОТ ПАРКУРА MINECRAFT v2.1")
    print("="*50)
    print("\nТРЕБОВАНИЯ:")
    print("1. Запуск от администратора")
    print("2. Чувствительность мыши = 0%")
    print("3. Оконный режим")
    print("="*50)
    
    # Проверка библиотек
    try:
        import subprocess
        
        required_packages = {
            'pyautogui': 'pyautogui',
            'keyboard': 'keyboard', 
            'PIL': 'pillow',
            'pynput': 'pynput',
            'win32api': 'pywin32'
        }
        
        for module, package in required_packages.items():
            try:
                __import__(module)
                print(f"✓ {package}")
            except ImportError:
                print(f"✗ {package} не установлен")
                print(f"  Установите: pip install {package}")
                sys.exit(1)
                
    except Exception as e:
        print(f"Ошибка проверки: {e}")
    
    input("\nНажмите Enter для запуска...")
    
    try:
        bot = ParkourBot()
        bot.start()
    except Exception as e:
        print(f"Ошибка запуска: {e}")
        traceback.print_exc()
        input("\nНажмите Enter для выхода...")