from abc import ABC, abstractmethod from typing import Optional import sys import os # Agregar el directorio padre al path para importar config sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from config import PATCH_CONFIG class Patch(ABC): """Clase base para todos los tipos de parches""" @abstractmethod def create_patch(self, original_data: bytes) -> bytes: """Crea el código del parche""" pass @abstractmethod def get_patch_size(self) -> int: """Retorna el tamaño del parche""" pass @abstractmethod def get_description(self) -> str: """Retorna la descripción del parche""" pass class StaminaPatch(Patch): """Parche específico para stamina infinita""" def create_patch(self, original_data: bytes) -> bytes: """Crea el código de parche para stamina infinita""" # Obtener configuración del patch desde config stamina_config = PATCH_CONFIG['stamina'] # Preservar el byte del salto original jump_offset = original_data[1] if len(original_data) > 1 else 0x16 # Usar instrucciones desde configuración instructions = stamina_config['instructions'].copy() instructions[1] = jump_offset # Actualizar el offset del salto return bytes(instructions) def get_patch_size(self) -> int: """Retorna el tamaño del parche de stamina""" return 18 def get_description(self) -> str: """Descripción del parche de stamina""" return PATCH_CONFIG['stamina']['description'] class SpeedPatch(Patch): """Parche específico para velocidad de movimiento""" def __init__(self, speed_multiplier: str = '2x'): self.speed_multiplier = speed_multiplier def create_patch(self, original_data: bytes) -> bytes: """Crea el código de parche para velocidad modificada""" # Obtener configuración del patch desde config speed_config = PATCH_CONFIG['speed'] # Obtener el patrón de velocidad deseado if self.speed_multiplier in speed_config['speed_multipliers']: return bytes(speed_config['speed_multipliers'][self.speed_multiplier]) else: # Fallback a velocidad normal si no se encuentra el multiplicador return bytes(speed_config['speed_multipliers']['1x']) def get_patch_size(self) -> int: """Retorna el tamaño del parche de velocidad""" return 16 def get_description(self) -> str: """Descripción del parche de velocidad""" return f"{PATCH_CONFIG['speed']['description']} (Multiplicador: {self.speed_multiplier})" class HealthPatch(Patch): """Parche para vida infinita (ejemplo de extensibilidad)""" def create_patch(self, original_data: bytes) -> bytes: """Placeholder para parche de vida""" # Implementación futura return b'\x90' * 8 # NOPs por ahora def get_patch_size(self) -> int: return 8 def get_description(self) -> str: return "Parche de vida infinita (no implementado)" class PatchFactory: """Factory para crear diferentes tipos de parches""" _patch_types = { 'stamina': StaminaPatch, 'speed': SpeedPatch, 'health': HealthPatch } @classmethod def create_patch(cls, patch_type: str, **kwargs) -> Optional[Patch]: """Crea un parche del tipo especificado""" patch_class = cls._patch_types.get(patch_type.lower()) if patch_class: if patch_type.lower() == 'speed': speed_multiplier = kwargs.get('speed_multiplier', '2x') return patch_class(speed_multiplier) else: return patch_class() return None @classmethod def get_available_patches(cls) -> list: """Retorna la lista de parches disponibles""" return list(cls._patch_types.keys()) @classmethod def get_speed_multipliers(cls) -> list: """Retorna la lista de multiplicadores de velocidad disponibles""" return list(PATCH_CONFIG['speed']['speed_multipliers'].keys())