### Prepare OptiFine Runtime with OptifineSetup Source: https://context7.com/modmuss50/optifabric/llms.txt Handles extraction, remapping, and caching of OptiFine classes. Requires a valid OptiFine installer or mod jar to function. ```java public class OptifineSetup { private File workingDir = new File(FabricLoader.getInstance().getGameDirectory(), ".optifine"); public Pair getRuntime() throws Throwable { File optifineModJar = OptifineVersion.findOptifineJar(); byte[] modHash = fileHash(optifineModJar); File versionDir = new File(workingDir, OptifineVersion.version); File remappedJar = new File(versionDir, "Optifine-mapped.jar"); File optifinePatches = new File(versionDir, "Optifine.classes"); // Check for cached version ClassCache classCache = null; if (remappedJar.exists() && optifinePatches.exists()) { classCache = ClassCache.read(optifinePatches); if (!Arrays.equals(classCache.getHash(), modHash)) { classCache = null; // Hash mismatch, regenerate } } if (remappedJar.exists() && classCache != null) { return Pair.of(remappedJar, classCache); } // Extract from installer if needed if (OptifineVersion.jarType == OptifineVersion.JarType.OPTFINE_INSTALLER) { File optifineMod = new File(versionDir, "/Optifine-mod.jar"); OptifineInstaller.extract(optifineModJar, optifineMod, getMinecraftJar().toFile()); optifineModJar = optifineMod; } // Remove SRG-named classes (Forge remnants) File jarOfTheFree = new File(versionDir, "/Optifine-jarofthefree.jar"); // ... de-volderifying process removes srg/ and net/minecraft/ entries // Fix lambda method names LambadaRebuiler rebuiler = new LambadaRebuiler(jarOfTheFree, getMinecraftJar().toFile()); rebuiler.buildLambadaMap(); // Remap to current runtime namespace File lambadaFixJar = new File(versionDir, "/Optifine-lambadafix.jar"); RemapUtils.mapJar(lambadaFixJar.toPath(), jarOfTheFree.toPath(), rebuiler, getLibs()); remapOptifine(lambadaFixJar.toPath(), remappedJar); // Generate and cache patched classes classCache = PatchSplitter.generateClassCache(remappedJar, optifinePatches, modHash); return Pair.of(remappedJar, classCache); } } ``` -------------------------------- ### Initialize Optifabric Early Loading Source: https://context7.com/modmuss50/optifabric/llms.txt Implements Runnable to handle early initialization, validation, and OptiFine runtime setup. This class must be registered as an early riser in fabric.mod.json. ```java // OptifabricSetup implements Runnable and is registered as an early riser // in fabric.mod.json under "mm:early_risers" public class OptifabricSetup implements Runnable { public static final String OPTIFABRIC_INCOMPATIBLE = "optifabric:incompatible"; public static File optifineRuntimeJar = null; @Override public void run() { // Validate Fabric loader version (requires >=0.7.0) if (!validateLoaderVersion()) return; // Check for mods that declare incompatibility if (!validateMods()) return; try { OptifineSetup optifineSetup = new OptifineSetup(); Pair runtime = optifineSetup.getRuntime(); // Add the optifine jar to the classpath ClassTinkerers.addURL(runtime.getLeft().toURI().toURL()); // Setup class injection OptifineInjector injector = new OptifineInjector(runtime.getRight()); injector.setup(); optifineRuntimeJar = runtime.getLeft(); } catch (Throwable e) { OptifabricError.setError("Failed to load optifine: " + e.getMessage()); throw new RuntimeException("Failed to setup optifine", e); } // Add compatibility mixins based on loaded mods if (FabricLoader.getInstance().isModLoaded("fabric-renderer-indigo")) { Mixins.addConfiguration("optifabric.indigofix.mixins.json"); } Mixins.addConfiguration("optifabric.optifine.mixins.json"); } } ``` -------------------------------- ### Inject OptiFine Classes with OptifineInjector Source: https://context7.com/modmuss50/optifabric/llms.txt Uses Fabric-ASM's ClassTinkerers to replace vanilla classes with OptiFine versions. Requires a pre-generated ClassCache. ```java public class OptifineInjector { ClassCache classCache; private final OptifineFixer optifineFixer = OptifineFixer.INSTANCE; public OptifineInjector(ClassCache classCache) { this.classCache = classCache; } public void setup() { // Register class replacements for all cached classes classCache.getClasses().forEach(s -> ClassTinkerers.addReplacement( s.replaceAll("/", ".").substring(0, s.length() - 6), transformer ) ); } // Transformer that replaces vanilla classes with OptiFine versions public final Consumer transformer = target -> { ClassNode source = getSourceClassNode(target); // Skip classes that cause issues if (optifineFixer.shouldSkip(target.name)) { return; } // Apply compatibility fixes optifineFixer.getFixers(target.name) .forEach(classFixer -> classFixer.fix(source, target)); // Replace class members target.methods = source.methods; target.fields = source.fields; target.interfaces = source.interfaces; target.superName = source.superName; // Make all members public for mixin compatibility target.access = modAccess(target.access); target.methods.forEach(m -> m.access = modAccess(m.access)); target.fields.forEach(f -> f.access = modAccess(f.access)); }; } ``` -------------------------------- ### Remap Jar Files with RemapUtils Source: https://context7.com/modmuss50/optifabric/llms.txt Provides utilities for remapping OptiFine jars between mapping namespaces using Fabric's TinyRemapper. ```java public class RemapUtils { // Create mapping provider from tiny mappings file public static IMappingProvider getTinyRemapper(File mappings, String from, String to) { return TinyUtils.createTinyMappingProvider(mappings.toPath(), from, to); } // Remap a jar file from one namespace to another public static void mapJar(Path output, Path input, IMappingProvider mappings, List libraries) throws IOException { Files.deleteIfExists(output); TinyRemapper remapper = TinyRemapper.newRemapper() .withMappings(mappings) .renameInvalidLocals(true) .rebuildSourceFilenames(true) .build(); try { OutputConsumerPath outputConsumer = new OutputConsumerPath(output); outputConsumer.addNonClassFiles(input); remapper.readInputs(input); // Add library classes for reference resolution for (Path path : libraries) { remapper.readClassPath(path); } remapper.apply(outputConsumer); outputConsumer.close(); remapper.finish(); } catch (Exception e) { remapper.finish(); throw new RuntimeException("Failed to remap jar", e); } } } ``` -------------------------------- ### Manage Optifine Loading Errors in OptifabricError Source: https://context7.com/modmuss50/optifabric/llms.txt Manages the error state and provides user-friendly error messages with help links when OptiFine loading fails. Errors are displayed in a confirmation screen on the title screen. ```java public class OptifabricError { private static String error = null; private static String errorURL = "https://github.com/modmuss50/OptiFabric/blob/master/README.md"; private static String helpButtonText = "Open Help"; public static boolean hasError() { return error != null; } public static void setError(String error) { OptifabricError.error = error; } public static void setError(String error, String url) { OptifabricError.error = error; OptifabricError.errorURL = url; } public static void setHelpButtonText(String text) { OptifabricError.helpButtonText = text; } } // Error display in title screen (via Mixin) @Mixin(TitleScreen.class) public abstract class MixinTitleScreen extends Screen { @Inject(method = "init", at = @At("RETURN")) private void init(CallbackInfo info) { // Show error dialog if OptiFine failed to load if (OptifabricError.hasError()) { ConfirmScreen confirmScreen = new ConfirmScreen( t -> { if (t) Util.getOperatingSystem().open(OptifabricError.getErrorURL()); else MinecraftClient.getInstance().scheduleStop(); }, new LiteralText(Formatting.RED + "There was an error loading OptiFabric!"), new LiteralText(OptifabricError.getError()), new LiteralText(OptifabricError.getHelpButtonText()).formatted(Formatting.GREEN), new LiteralText("Close Game").formatted(Formatting.RED) ); MinecraftClient.getInstance().openScreen(confirmScreen); } } } ``` -------------------------------- ### Register Class Compatibility Fixes in OptifineFixer Source: https://context7.com/modmuss50/optifabric/llms.txt Registers compatibility fixes for specific Minecraft classes when OptiFine is loaded. Uses intermediary class names for registration. ```java public class OptifineFixer { public static final OptifineFixer INSTANCE = new OptifineFixer(); private HashMap> classFixes = new HashMap<>(); private List skippedClass = new ArrayList<>(); private OptifineFixer() { // Register fixes for specific classes (using intermediary names) registerFix("class_851", new ChunkRendererFix()); // ChunkBuilder$BuiltChunk registerFix("class_778", new BlockModelRendererFix()); // BlockModelRenderer registerFix("class_309", new KeyboardFix()); // Keyboard registerFix("class_759", new HeldItemRendererFix()); // HeldItemRenderer registerFix("class_1059", new SpriteAtlasTextureFix()); // SpriteAtlasTexture registerFix("class_3898", new ThreadedAnvilChunkStorageFix()); // Skip classes that cause issues skipClass("class_702"); // ParticleManager skipClass("class_759$1"); // HeldItemRenderer$1 } public boolean shouldSkip(String className) { return skippedClass.contains(className); } public List getFixers(String className) { return classFixes.getOrDefault(className, Collections.emptyList()); } } // ClassFixer interface for implementing fixes public interface ClassFixer { void fix(ClassNode optifine, ClassNode minecraft); } ``` -------------------------------- ### Detect and Validate OptiFine Jar Source: https://context7.com/modmuss50/optifabric/llms.txt Scans the mods directory for OptiFine jars and categorizes them using the JarType enum. Throws an exception if multiple OptiFine jars are detected. ```java public class OptifineVersion { public static String version; public static String minecraftVersion; public static JarType jarType; // Find OptiFine jar in the mods folder public static File findOptifineJar() throws IOException { File modsDir = new File(FabricLoader.getInstance().getGameDirectory(), "mods"); File[] mods = modsDir.listFiles(); File optifineJar = null; if (mods != null) { for (File file : mods) { if (file.getName().endsWith(".jar")) { JarType type = getJarType(file); if (type == JarType.OPIFINE_MOD || type == JarType.OPTFINE_INSTALLER) { if (optifineJar != null) { OptifabricError.setError("Found 2 or more optifine jars!"); throw new FileNotFoundException("Multiple optifine jars"); } jarType = type; optifineJar = file; } } } } return optifineJar; } // Jar type determines how OptiFine should be processed public enum JarType { OPIFINE_MOD(false), // Pre-extracted mod jar OPTFINE_INSTALLER(false), // Installer that needs extraction INCOMPATIBE(true), // Wrong MC version or corrupted SOMETHINGELSE(false); // Not an OptiFine jar boolean error; JarType(boolean error) { this.error = error; } } } ``` -------------------------------- ### Write ClassNode to Bytecode using ASM Source: https://context7.com/modmuss50/optifabric/llms.txt Writes a ClassNode back to bytecode using ASM. Utilizes COMPUTE_MAXS and COMPUTE_FRAMES for efficient bytecode generation. ```java public static byte[] writeClassToBytes(ClassNode classNode) { ClassWriter writer = new ClassWriter( ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES ); classNode.accept(writer); return writer.toByteArray(); } ``` -------------------------------- ### Store and Serialize Patched Classes with ClassCache Source: https://context7.com/modmuss50/optifabric/llms.txt Use ClassCache to store and serialize patched class bytecode in a compressed format. It supports reading from and saving to gzipped files. ```java public class ClassCache { private byte[] hash; private Map classes = new HashMap<>(); public ClassCache(byte[] hash) { this.hash = hash; } public void addClass(String name, byte[] bytes) { if (classes.containsKey(name)) { throw new UnsupportedOperationException(name + " is already in ClassCache"); } classes.put(name, bytes); } public byte[] getAndRemove(String name) { byte[] bytes = classes.get(name); classes.remove(name); return bytes; } // Read cached classes from gzipped file public static ClassCache read(File input) throws IOException { FileInputStream fis = new FileInputStream(input); GZIPInputStream gis = new GZIPInputStream(fis); DataInputStream dis = new DataInputStream(gis); ClassCache classCache = new ClassCache(); // Read hash for validation int hashSize = dis.readInt(); byte[] hash = new byte[hashSize]; dis.readFully(hash); classCache.hash = hash; // Read all cached classes int count = dis.readInt(); for (int i = 0; i < count; i++) { String name = readString(dis); byte[] bytes = readBytes(dis); classCache.classes.put(name, bytes); } return classCache; } // Save cache to gzipped file public void save(File output) throws IOException { FileOutputStream fos = new FileOutputStream(output); GZIPOutputStream gos = new GZIPOutputStream(fos); DataOutputStream dos = new DataOutputStream(gos); dos.writeInt(hash.length); dos.write(hash); dos.writeInt(classes.size()); for (Map.Entry clazz : classes.entrySet()) { writeString(dos, clazz.getKey()); writeBytes(dos, clazz.getValue()); } dos.close(); } } ``` -------------------------------- ### Resolve Fabric Mappings Source: https://context7.com/modmuss50/optifabric/llms.txt Provides methods to map intermediary class and method names to their current runtime namespace using the Fabric MappingResolver. ```java public class RemappingUtils { private static final MappingResolver resolver = FabricLoader.getInstance().getMappingResolver(); private static final String INTERMEDIARY = "intermediary"; // Get runtime class name from intermediary name public static String getClassName(String className) { return fromIntermediaryDot(className).replaceAll("\\.", "/"); } // Map intermediary class name to current runtime namespace public static String fromIntermediaryDot(String className) { return resolver.mapClassName(INTERMEDIARY, "net.minecraft." + className); } // Map intermediary method name to current runtime namespace public static String getMethodName(String owner, String methodName, String desc) { return resolver.mapMethodName(INTERMEDIARY, "net.minecraft." + owner, methodName, desc); } } ``` -------------------------------- ### Read ClassNode from Bytecode using ASM Source: https://context7.com/modmuss50/optifabric/llms.txt Reads a ClassNode from raw bytecode using ASM. Ensures the input byte array is not null before proceeding. ```java public static ClassNode readClassFromBytes(byte[] bytes) { Validate.notNull(bytes, "Cannot read null bytes"); ClassNode classNode = new ClassNode(); ClassReader classReader = new ClassReader(bytes); classReader.accept(classNode, ClassReader.SKIP_FRAMES); return classNode; } ``` -------------------------------- ### Read ClassNode from JAR Entry using ASM Source: https://context7.com/modmuss50/optifabric/llms.txt Reads a ClassNode from a JarEntry within a JarFile. Handles potential IOExceptions during file processing. ```java public static ClassNode asClassNode(JarEntry entry, JarFile jarFile) throws IOException { InputStream is = jarFile.getInputStream(entry); byte[] bytes = IOUtils.toByteArray(is); return readClassFromBytes(bytes); } ``` -------------------------------- ### Check for Synthetic Flag in Method/Field Flags Source: https://context7.com/modmuss50/optifabric/llms.txt Checks if the synthetic flag is set in the given integer flags, commonly used for methods or fields. ```java public static boolean isSynthetic(int flags) { return (flags & Opcodes.ACC_SYNTHETIC) != 0; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.