org.spongepowered.asm.mixin.MixinEnvironment Java Examples

The following examples show how to use org.spongepowered.asm.mixin.MixinEnvironment. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ExtensionClassExporter.java    From Mixin with MIT License 6 votes vote down vote up
@Override
public void export(MixinEnvironment env, String name, boolean force, ClassNode classNode) {
    // Export transformed class for debugging purposes
    if (force || env.getOption(Option.DEBUG_EXPORT)) {
        String filter = env.getOptionValue(Option.DEBUG_EXPORT_FILTER);
        if (force || filter == null || this.applyFilter(filter, name)) {
            Section exportTimer = MixinEnvironment.getProfiler().begin("debug.export");
            
            File outputFile = this.dumpClass(name.replace('.', '/'), classNode);
            if (this.decompiler != null) {
                this.decompiler.decompile(outputFile);
            }
            exportTimer.end();
        }
    }
}
 
Example #2
Source File: MixinClassGenerator.java    From Mixin with MIT License 6 votes vote down vote up
synchronized boolean generateClass(MixinEnvironment environment, String name, ClassNode classNode) {
    if (name == null) {
        MixinClassGenerator.logger.warn("MixinClassGenerator tried to generate a class with no name!");
        return false;
    }
    
    for (IClassGenerator generator : this.extensions.getGenerators()) {
        Section genTimer = this.profiler.begin("generator", generator.getClass().getSimpleName().toLowerCase(Locale.ROOT));
        boolean success = generator.generate(name, classNode);
        genTimer.end();
        if (success) {
            if (this.auditTrail != null) {
                this.auditTrail.onGenerate(name, generator.getName());
            }
            this.extensions.export(environment, name.replace('.', '/'), false, classNode);
            return true;
        }
    }
    
    return false;
}
 
Example #3
Source File: MixinTransformationHandler.java    From Mixin with MIT License 6 votes vote down vote up
@Override
public synchronized boolean processClass(Phase phase, ClassNode classNode, Type classType, String reason) {
    if (phase == Phase.BEFORE) {
        return false;
    }
    
    MixinTransformer transformer = null;
    if (this.transformer == null) {
        synchronized (this.initialisationLock) {
            transformer = this.transformer;
            if (transformer == null) {
                transformer = this.transformer = new MixinTransformer();
                this.registry = transformer.getExtensions().getSyntheticClassRegistry();
            }
        }
    } else {
        transformer = this.transformer;
    }

    MixinEnvironment environment = MixinEnvironment.getCurrentEnvironment();
    ISyntheticClassInfo syntheticClass = this.registry.findSyntheticClass(classType.getClassName());
    if (syntheticClass != null) {
        return transformer.generateClass(environment, classType.getClassName(), classNode);
    }
    return transformer.transformClass(environment, classType.getClassName(), classNode);
}
 
Example #4
Source File: MixinServiceLaunchWrapper.java    From Mixin with MIT License 6 votes vote down vote up
/**
 * Loads class bytecode from the classpath
 * 
 * @param className Name of the class to load
 * @param runTransformers True to run the loaded bytecode through the
 *      delegate transformer chain
 * @return Transformed class bytecode for the specified class
 * @throws ClassNotFoundException if the specified class could not be loaded
 * @throws IOException if an error occurs whilst reading the specified class
 */
@Deprecated
public byte[] getClassBytes(String className, boolean runTransformers) throws ClassNotFoundException, IOException {
    String transformedName = className.replace('/', '.');
    String name = this.unmapClassName(transformedName);
    
    Profiler profiler = MixinEnvironment.getProfiler();
    Section loadTime = profiler.begin(Profiler.ROOT, "class.load");
    byte[] classBytes = this.getClassBytes(name, transformedName);
    loadTime.end();

    if (runTransformers) {
        Section transformTime = profiler.begin(Profiler.ROOT, "class.transform");
        classBytes = this.applyTransformers(name, transformedName, classBytes, profiler);
        transformTime.end();
    }

    if (classBytes == null) {
        throw new ClassNotFoundException(String.format("The specified class '%s' was not found", transformedName));
    }

    return classBytes;
}
 
Example #5
Source File: MixinTransformer.java    From Mixin with MIT License 6 votes vote down vote up
public MixinTransformer() {
    MixinEnvironment environment = MixinEnvironment.getCurrentEnvironment();
    
    Object globalMixinTransformer = environment.getActiveTransformer();
    if (globalMixinTransformer instanceof IMixinTransformer) {
        throw new MixinException("Terminating MixinTransformer instance " + this);
    }
    
    // I am a leaf on the wind
    environment.setActiveTransformer(this);
    
    this.syntheticClassRegistry = new SyntheticClassRegistry();
    this.extensions = new Extensions(this.syntheticClassRegistry);
    
    this.hotSwapper = this.initHotSwapper(environment);

    this.processor = new MixinProcessor(environment, this.extensions, this.hotSwapper);
    this.generator = new MixinClassGenerator(environment, this.extensions);
    
    DefaultExtensions.create(environment, this.extensions, this.syntheticClassRegistry);
}
 
Example #6
Source File: MixinTransformer.java    From Mixin with MIT License 6 votes vote down vote up
private IHotSwap initHotSwapper(MixinEnvironment environment) {
    if (!environment.getOption(Option.HOT_SWAP)) {
        return null;
    }

    try {
        MixinProcessor.logger.info("Attempting to load Hot-Swap agent");
        @SuppressWarnings("unchecked")
        Class<? extends IHotSwap> clazz =
                (Class<? extends IHotSwap>)Class.forName(MixinTransformer.MIXIN_AGENT_CLASS);
        Constructor<? extends IHotSwap> ctor = clazz.getDeclaredConstructor(IMixinTransformer.class);
        return ctor.newInstance(this);
    } catch (Throwable th) {
        MixinProcessor.logger.info("Hot-swap agent could not be loaded, hot swapping of mixins won't work. {}: {}",
                th.getClass().getSimpleName(), th.getMessage());
    }

    return null;
}
 
Example #7
Source File: FabricLauncherBase.java    From fabric-loader with Apache License 2.0 6 votes vote down vote up
protected static void finishMixinBootstrapping() {
	if (mixinReady) {
		throw new RuntimeException("Must not call FabricLauncherBase.finishMixinBootstrapping() twice!");
	}

	try {
		Method m = MixinEnvironment.class.getDeclaredMethod("gotoPhase", MixinEnvironment.Phase.class);
		m.setAccessible(true);
		m.invoke(null, MixinEnvironment.Phase.INIT);
		m.invoke(null, MixinEnvironment.Phase.DEFAULT);
	} catch (Exception e) {
		throw new RuntimeException(e);
	}

	mixinReady = true;
}
 
Example #8
Source File: MixinProcessor.java    From Mixin with MIT License 6 votes vote down vote up
/**
 * Add configurations from the supplied mixin environment to the configs set
 * 
 * @param environment Environment to query
 */
private void selectConfigs(MixinEnvironment environment) {
    for (Iterator<Config> iter = Mixins.getConfigs().iterator(); iter.hasNext();) {
        Config handle = iter.next();
        try {
            MixinConfig config = handle.get();
            if (config.select(environment)) {
                iter.remove();
                MixinProcessor.logger.log(this.verboseLoggingLevel, "Selecting config {}", config);
                config.onSelect();
                this.pendingConfigs.add(config);
            }
        } catch (Exception ex) {
            MixinProcessor.logger.warn(String.format("Failed to select mixin config: %s", handle), ex);
        }
    }
    
    Collections.sort(this.pendingConfigs);
}
 
Example #9
Source File: MixinProcessor.java    From Mixin with MIT License 6 votes vote down vote up
/**
 * Apply mixins for specified target class to the class described by the
 * supplied byte array.
 * 
 * @param environment current environment
 * @param context target class context
 */
private void applyMixins(MixinEnvironment environment, TargetClassContext context) {
    Section timer = this.profiler.begin("preapply");
    this.extensions.preApply(context);
    timer = timer.next("apply");
    context.applyMixins();
    timer = timer.next("postapply");
    boolean export = false;
    try {
        this.extensions.postApply(context);
        export = true;
    } catch (ValidationFailedException ex) {
        MixinProcessor.logger.info(ex.getMessage());
        // If verify is enabled and failed, write out the bytecode to allow us to inspect it
        export |= context.isExportForced() || environment.getOption(Option.DEBUG_EXPORT);
    }
    timer.end();
    if (export) {
        this.extensions.export(this.currentEnvironment, context.getClassName(), context.isExportForced(), context.getClassNode());
    }
    for (InvalidMixinException suppressed : context.getSuppressedExceptions()) {
        this.handleMixinApplyError(context.getClassName(), suppressed, environment);
    }
}
 
Example #10
Source File: MixinConfig.java    From Mixin with MIT License 6 votes vote down vote up
/**
 * Called immediately after deserialisation
 * 
 * @param name Mixin config name
 * @param fallbackEnvironment Fallback environment if not specified in
 *      config
 * @return true if the config was successfully initialised and should be
 *      returned, or false if initialisation failed and the config should
 *      be discarded
 */
private boolean onLoad(IMixinService service, String name, MixinEnvironment fallbackEnvironment) {
    this.service = service;
    this.name = name;
    
    // If parent is specified, don't perform postinit until parent is assigned
    if (!Strings.isNullOrEmpty(this.parentName)) {
        return true;
    }
    
    // If no parent, initialise config options
    this.env = this.parseSelector(this.selector, fallbackEnvironment);
    this.required = this.requiredValue != null && this.requiredValue.booleanValue() && !this.env.getOption(Option.IGNORE_REQUIRED);
    this.initPriority(IMixinConfig.DEFAULT_PRIORITY, IMixinConfig.DEFAULT_PRIORITY);
    
    if (this.injectorOptions == null) {
        this.injectorOptions = new InjectorOptions();
    }
    
    if (this.overwriteOptions == null) {
        this.overwriteOptions = new OverwriteOptions();
    }
    
    return this.postInit();
}
 
Example #11
Source File: MixinConfig.java    From Mixin with MIT License 6 votes vote down vote up
private MixinEnvironment parseSelector(String target, MixinEnvironment fallbackEnvironment) {
    if (target != null) {
        String[] selectors = target.split("[&\\| ]");
        for (String sel : selectors) {
            sel = sel.trim();
            Pattern environmentSelector = Pattern.compile("^@env(?:ironment)?\\(([A-Z]+)\\)$");
            Matcher environmentSelectorMatcher = environmentSelector.matcher(sel);
            if (environmentSelectorMatcher.matches()) {
                // only parse first env selector
                return MixinEnvironment.getEnvironment(Phase.forName(environmentSelectorMatcher.group(1)));
            }              
        }
        
        Phase phase = Phase.forName(target);
        if (phase != null) {
            return MixinEnvironment.getEnvironment(phase);
        }
    }
    return fallbackEnvironment;
}
 
Example #12
Source File: ExtensionClassExporter.java    From Mixin with MIT License 6 votes vote down vote up
private IDecompiler initDecompiler(MixinEnvironment env, File outputPath) {
    if (!env.getOption(Option.DEBUG_EXPORT_DECOMPILE)) {
        return null;
    }
    
    try {
        boolean as = env.getOption(Option.DEBUG_EXPORT_DECOMPILE_THREADED);
        ExtensionClassExporter.logger.info("Attempting to load Fernflower decompiler{}", as ? " (Threaded mode)" : "");
        String className = ExtensionClassExporter.DECOMPILER_CLASS + (as ? "Async" : "");
        @SuppressWarnings("unchecked")
        Class<? extends IDecompiler> clazz = (Class<? extends IDecompiler>)Class.forName(className);
        Constructor<? extends IDecompiler> ctor = clazz.getDeclaredConstructor(File.class);
        IDecompiler decompiler = ctor.newInstance(outputPath);
        ExtensionClassExporter.logger.info("Fernflower decompiler was successfully initialised, exported classes will be decompiled{}",
                as ? " in a separate thread" : "");
        return decompiler;
    } catch (Throwable th) {
        ExtensionClassExporter.logger.info("Fernflower could not be loaded, exported classes will not be decompiled. {}: {}",
                th.getClass().getSimpleName(), th.getMessage());
    }
    return null;
}
 
Example #13
Source File: MixinApplicatorStandard.java    From Mixin with MIT License 5 votes vote down vote up
MixinApplicatorStandard(TargetClassContext context) {
    this.context = context;
    this.targetName = context.getClassName();
    this.targetClass = context.getClassNode();
    this.targetClassInfo = context.getClassInfo();
    
    ExtensionClassExporter exporter = context.getExtensions().<ExtensionClassExporter>getExtension(ExtensionClassExporter.class);
    this.mergeSignatures = exporter.isDecompilerActive()
            && MixinEnvironment.getCurrentEnvironment().getOption(Option.DEBUG_EXPORT_DECOMPILE_MERGESIGNATURES);
    
    this.auditTrail = MixinService.getService().getAuditTrail();
}
 
Example #14
Source File: MixinApplicatorStandard.java    From Mixin with MIT License 5 votes vote down vote up
private InitialiserInjectionMode getInitialiserInjectionMode(MixinEnvironment environment) {
    String strMode = environment.getOptionValue(Option.INITIALISER_INJECTION_MODE);
    if (strMode == null) {
        return InitialiserInjectionMode.DEFAULT;
    }
    try {
        return InitialiserInjectionMode.valueOf(strMode.toUpperCase(Locale.ROOT));
    } catch (Exception ex) {
        this.logger.warn("Could not parse unexpected value \"{}\" for mixin.initialiserInjectionMode, reverting to DEFAULT", strMode);
        return InitialiserInjectionMode.DEFAULT;
    }
}
 
Example #15
Source File: DefaultExtensions.java    From Mixin with MIT License 5 votes vote down vote up
static void create(final MixinEnvironment environment, final Extensions extensions, final SyntheticClassRegistry registry) {
    IConsumer<ISyntheticClassInfo> registryDelegate = new IConsumer<ISyntheticClassInfo>() {
        @Override
        public void accept(ISyntheticClassInfo item) {
            registry.registerSyntheticClass(item);
        }
    };
    
    extensions.add(new ArgsClassGenerator(registryDelegate));
    extensions.add(new InnerClassGenerator(registryDelegate));

    extensions.add(new ExtensionClassExporter(environment));
    extensions.add(new ExtensionCheckClass());
    extensions.add(new ExtensionCheckInterfaces());
}
 
Example #16
Source File: MixinTransformer.java    From Mixin with MIT License 5 votes vote down vote up
/**
 * Generate the specified mixin-synthetic class
 * 
 * @param environment Current environment
 * @param name Class name to generate
 * @return Generated bytecode or <tt>null</tt> if no class was generated
 */
public byte[] generateClass(MixinEnvironment environment, String name) {
    ClassNode classNode = MixinTransformer.createEmptyClass(name);
    if (this.generator.generateClass(environment, name, classNode)) {
        return this.writeClass(classNode);
    }
    return null;
}
 
Example #17
Source File: MixinProcessor.java    From Mixin with MIT License 5 votes vote down vote up
private void checkSelect(MixinEnvironment environment) {
    if (this.currentEnvironment != environment) {
        this.select(environment);
        return;
    }
    
    int unvisitedCount = Mixins.getUnvisitedCount();
    if (unvisitedCount > 0 && this.transformedCount == 0) {
        this.select(environment);
    }
}
 
Example #18
Source File: MixinProcessor.java    From Mixin with MIT License 5 votes vote down vote up
private void select(MixinEnvironment environment) {
    this.verboseLoggingLevel = (environment.getOption(Option.DEBUG_VERBOSE)) ? Level.INFO : Level.DEBUG;
    if (this.transformedCount > 0) {
        MixinProcessor.logger.log(this.verboseLoggingLevel, "Ending {}, applied {} mixins", this.currentEnvironment, this.transformedCount);
    }
    String action = this.currentEnvironment == environment ? "Checking for additional" : "Preparing";
    MixinProcessor.logger.log(this.verboseLoggingLevel, "{} mixins for {}", action, environment);
    
    this.profiler.setActive(true);
    this.profiler.mark(environment.getPhase().toString() + ":prepare");
    Section prepareTimer = this.profiler.begin("prepare");
    
    this.selectConfigs(environment);
    this.extensions.select(environment);
    int totalMixins = this.prepareConfigs(environment);
    this.currentEnvironment = environment;
    this.transformedCount = 0;

    prepareTimer.end();
    
    long elapsedMs = prepareTimer.getTime();
    double elapsedTime = prepareTimer.getSeconds();
    if (elapsedTime > 0.25D) {
        long loadTime = this.profiler.get("class.load").getTime();
        long transformTime = this.profiler.get("class.transform").getTime();
        long pluginTime = this.profiler.get("mixin.plugin").getTime();
        String elapsed = new DecimalFormat("###0.000").format(elapsedTime);
        String perMixinTime = new DecimalFormat("###0.0").format(((double)elapsedMs) / totalMixins);
        
        MixinProcessor.logger.log(this.verboseLoggingLevel, "Prepared {} mixins in {} sec ({}ms avg) ({}ms load, {}ms transform, {}ms plugin)",
                totalMixins, elapsed, perMixinTime, loadTime, transformTime, pluginTime);
    }

    this.profiler.mark(environment.getPhase().toString() + ":apply");
    this.profiler.setActive(environment.getOption(Option.DEBUG_PROFILER));
}
 
Example #19
Source File: MixinConfig.java    From Mixin with MIT License 5 votes vote down vote up
@SuppressWarnings("deprecation")
private void initCompatibilityLevel() {
    if (this.compatibility == null) {
        return;
    }
    
    CompatibilityLevel level = CompatibilityLevel.valueOf(this.compatibility.trim().toUpperCase(Locale.ROOT));
    CompatibilityLevel current = MixinEnvironment.getCompatibilityLevel();
    
    if (level == current) {
        return;
    }
    
    // Current level is higher than required but too new to support it
    if (current.isAtLeast(level)) {
        if (!current.canSupport(level)) {
            throw new MixinInitialisationError("Mixin config " + this.name + " requires compatibility level " + level + " which is too old");
        }
    }
    
    // Current level is lower than required but current level prohibits elevation
    if (!current.canElevateTo(level)) {
        throw new MixinInitialisationError("Mixin config " + this.name + " requires compatibility level " + level + " which is prohibited by "
                + current);
    }
    
    MixinEnvironment.setCompatibilityLevel(level);
}
 
Example #20
Source File: MixinInfo.java    From Mixin with MIT License 5 votes vote down vote up
@Override
void validateTarget(String targetName, ClassInfo targetInfo) {
    boolean targetIsInterface = targetInfo.isInterface();
    if (targetIsInterface && !MixinEnvironment.getCompatibilityLevel().supports(LanguageFeature.METHODS_IN_INTERFACES)) {
        throw new InvalidMixinException(this.mixin, "Accessor mixin targetting an interface is not supported in current enviromnment");
    }
}
 
Example #21
Source File: Extensions.java    From Mixin with MIT License 5 votes vote down vote up
/**
 * Selectively activate extensions based on the current environment
 * 
 * @param environment current environment
 */
public void select(MixinEnvironment environment) {
    Builder<IExtension> activeExtensions = ImmutableList.<IExtension>builder();

    for (IExtension extension : this.extensions) {
        if (extension.checkActive(environment)) {
            activeExtensions.add(extension);
        }
    }
    
    this.activeExtensions = activeExtensions.build();
}
 
Example #22
Source File: ExtensionClassExporter.java    From Mixin with MIT License 5 votes vote down vote up
public ExtensionClassExporter(MixinEnvironment env) {
    this.decompiler = this.initDecompiler(env, new File(Constants.DEBUG_OUTPUT_DIR, ExtensionClassExporter.EXPORT_JAVA_DIR));

    try {
        MoreFiles.deleteRecursively(this.classExportDir.toPath(), RecursiveDeleteOption.ALLOW_INSECURE);
    } catch (IOException ex) {
        ExtensionClassExporter.logger.debug("Error cleaning class output directory: {}", ex.getMessage());
    }
}
 
Example #23
Source File: MixinProcessor.java    From Mixin with MIT License 5 votes vote down vote up
/**
 * ctor 
 */
MixinProcessor(MixinEnvironment environment, Extensions extensions, IHotSwap hotSwapper) {
    this.lock = this.service.getReEntranceLock();
    
    this.extensions = extensions;
    this.hotSwapper = hotSwapper;
    this.postProcessor = new MixinPostProcessor(this.sessionId);
    
    this.profiler = MixinEnvironment.getProfiler();
    this.auditTrail = this.service.getAuditTrail();
}
 
Example #24
Source File: MixinInfo.java    From Mixin with MIT License 5 votes vote down vote up
@Override
void validate(State state, List<ClassInfo> targetClasses) {
    if (!MixinEnvironment.getCompatibilityLevel().supports(LanguageFeature.METHODS_IN_INTERFACES)) {
        throw new InvalidMixinException(this.mixin, "Interface mixin not supported in current enviromnment");
    }
    
    ClassNode classNode = state.getValidationClassNode();
    
    if (!"java/lang/Object".equals(classNode.superName)) {
        throw new InvalidMixinException(this.mixin, "Super class of " + this + " is invalid, found " 
                + classNode.superName.replace('/', '.'));
    }
}
 
Example #25
Source File: MixinInfo.java    From Mixin with MIT License 5 votes vote down vote up
private void validateClassVersion() {
    if (this.validationClassNode.version > MixinEnvironment.getCompatibilityLevel().classVersion()) {
        String helpText = ".";
        for (CompatibilityLevel level : CompatibilityLevel.values()) {
            if (level.classVersion() >= this.validationClassNode.version) {
                helpText = String.format(". Mixin requires compatibility level %s or above.", level.name()); 
            }
        }
        
        throw new InvalidMixinException(MixinInfo.this, "Unsupported mixin class version " + this.validationClassNode.version + helpText);
    }
}
 
Example #26
Source File: TargetClassContext.java    From Mixin with MIT License 5 votes vote down vote up
TargetClassContext(MixinEnvironment env, Extensions extensions, String sessionId, String name, ClassNode classNode, SortedSet<MixinInfo> mixins) {
    this.env = env;
    this.extensions = extensions;
    this.sessionId = sessionId;
    this.className = name;
    this.classNode = classNode;
    this.classInfo = ClassInfo.fromClassNode(classNode);
    this.signature = this.classInfo.getSignature();
    this.mixins = mixins;
    this.sourceMap = new SourceMap(classNode.sourceFile);
    this.sourceMap.addFile(this.classNode);
}
 
Example #27
Source File: MixinPostProcessor.java    From Mixin with MIT License 5 votes vote down vote up
private boolean processAccessor(ClassNode classNode, MixinInfo mixin) {
    if (!MixinEnvironment.getCompatibilityLevel().supports(LanguageFeature.METHODS_IN_INTERFACES)) {
        return false;
    }
    
    boolean transformed = false;
    MixinClassNode mixinClassNode = mixin.getClassNode(0);
    ClassInfo targetClass = mixin.getTargets().get(0);
    
    for (MixinMethodNode methodNode : mixinClassNode.mixinMethods) {
        if (!Bytecode.hasFlag(methodNode, Opcodes.ACC_STATIC)) {
            continue;
        }
        
        AnnotationNode accessor = methodNode.getVisibleAnnotation(Accessor.class);
        AnnotationNode invoker = methodNode.getVisibleAnnotation(Invoker.class);
        if (accessor != null || invoker != null) {
            Method method = this.getAccessorMethod(mixin, methodNode, targetClass);
            MixinPostProcessor.createProxy(methodNode, targetClass, method);
            Annotations.setVisible(methodNode, MixinProxy.class, "sessionId", this.sessionId);
            classNode.methods.add(methodNode);
            transformed = true;
        }
    }
    
    if (!transformed) {
        return false;
    }
    
    Bytecode.replace(mixinClassNode, classNode);
    return true;
}
 
Example #28
Source File: MixinTargetContext.java    From Mixin with MIT License 5 votes vote down vote up
/**
 * Mark this mixin as requiring the specified class version in the context
 * of the current target
 * 
 * @param version version to require
 */
protected void requireVersion(int version) {
    this.minRequiredClassVersion = Math.max(this.minRequiredClassVersion, version);
    
    // This validation is done on the mixin beforehand, however it's still
    // possible that an upstream transformer can inject java 7 instructions
    // without updating the class version.
    if (version > MixinEnvironment.getCompatibilityLevel().classVersion()) {
        throw new InvalidMixinException(this, "Unsupported mixin class version " + version);
    }
}
 
Example #29
Source File: MixinTransformer.java    From Mixin with MIT License 5 votes vote down vote up
/**
 * You need to ask yourself why you're reading this comment  
 */
private static ClassNode createEmptyClass(String name) {
    ClassNode classNode = new ClassNode(ASM.API_VERSION);
    classNode.name = name.replace('.', '/');
    classNode.version = MixinEnvironment.getCompatibilityLevel().classVersion();
    classNode.superName = Constants.OBJECT;
    return classNode;
}
 
Example #30
Source File: TweakerMixinLoader.java    From LiquidBounce with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void injectIntoClassLoader(LaunchClassLoader classLoader) {
    System.out.println("[LiquidBounce] Injecting with TweakerMixinLoader.");

    MixinBootstrap.init();
    Mixins.addConfiguration("liquidbounce.vanilla.mixins.json");
    MixinEnvironment.getDefaultEnvironment().setSide(MixinEnvironment.Side.CLIENT);

    classLoader.registerTransformer(AbstractJavaLinkerTransformer.class.getName());
}