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 |
@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 |
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 |
@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 |
/** * 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 |
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 |
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 |
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 |
/** * 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 |
/** * 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 |
/** * 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 |
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 |
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 |
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 |
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 |
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 |
/** * 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 |
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 |
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 |
@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 |
@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 |
/** * 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 |
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 |
/** * 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 |
@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 |
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 |
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 |
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 |
/** * 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 |
/** * 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 |
@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()); }