diff --git a/src/launchwrapper/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentFMLLegacy.java b/src/launchwrapper/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentFMLLegacy.java
index ca195b70b..56a34f454 100644
--- a/src/launchwrapper/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentFMLLegacy.java
+++ b/src/launchwrapper/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentFMLLegacy.java
@@ -140,11 +140,7 @@ public class MixinPlatformAgentFMLLegacy extends MixinPlatformAgentAbstract impl
@Override
public AcceptResult accept(MixinPlatformManager manager, IContainerHandle handle) {
- try {
- this.clCoreModManager = MixinPlatformAgentFMLLegacy.getCoreModManagerClass();
- } catch (ClassNotFoundException ex) {
- MixinPlatformAgentAbstract.logger.info("FML platform manager could not load class {}. Proceeding without FML support.",
- ex.getMessage());
+ if (this.getCoreModManagerClass() == null) {
return AcceptResult.INVALID;
}
@@ -298,30 +294,6 @@ public String getPhaseProvider() {
public void prepare() {
this.initInjectionState |= MixinPlatformAgentFMLLegacy.isTweakerQueued(MixinPlatformAgentFMLLegacy.FML_TWEAKER_INJECTION);
}
-
- /* (non-Javadoc)
- * @see org.spongepowered.asm.launch.IMixinPlatformAgent
- * #initPrimaryContainer()
- */
- @Override
- public void initPrimaryContainer() {
- if (this.clCoreModManager != null) {
-// MixinEnvironment.registerPhaseProvider(MixinPlatformAgentFMLLegacy.class.getName() + "$PhaseProvider");
- this.injectRemapper();
- }
- }
-
- private void injectRemapper() {
- try {
- MixinPlatformAgentAbstract.logger.debug("Creating FML remapper adapter: {}", MixinPlatformAgentFMLLegacy.FML_REMAPPER_ADAPTER_CLASS);
- Class> clFmlRemapperAdapter = Class.forName(MixinPlatformAgentFMLLegacy.FML_REMAPPER_ADAPTER_CLASS, true, Launch.classLoader);
- Method mdCreate = clFmlRemapperAdapter.getDeclaredMethod("create");
- IRemapper remapper = (IRemapper)mdCreate.invoke(null);
- MixinEnvironment.getDefaultEnvironment().getRemappers().add(remapper);
- } catch (Exception ex) {
- MixinPlatformAgentAbstract.logger.debug("Failed instancing FML remapper adapter, things will probably go horribly for notch-obf'd mods!");
- }
- }
/* (non-Javadoc)
* @see org.spongepowered.asm.launch.platform.IMixinPlatformAgent#inject()
@@ -357,6 +329,30 @@ protected final boolean checkForCoInitialisation() {
return !MixinPlatformAgentFMLLegacy.isTweakerQueued(MixinPlatformAgentFMLLegacy.FML_TWEAKER_DEOBF);
}
+ /**
+ * Attempt to get the FML CoreModManager, tries the post-1.8 namespace first
+ * and falls back to 1.7.10 if class lookup fails
+ */
+ private Class> getCoreModManagerClass() {
+ if (this.clCoreModManager != null) {
+ return this.clCoreModManager;
+ }
+
+ try {
+ try {
+ this.clCoreModManager = Class.forName(GlobalProperties.getString(
+ GlobalProperties.Keys.FML_CORE_MOD_MANAGER, MixinPlatformAgentFMLLegacy.CORE_MOD_MANAGER_CLASS));
+ } catch (ClassNotFoundException ex) {
+ this.clCoreModManager = Class.forName(MixinPlatformAgentFMLLegacy.CORE_MOD_MANAGER_CLASS_LEGACY);
+ }
+ } catch (ClassNotFoundException ex) {
+ MixinPlatformAgentAbstract.logger.info("FML platform manager could not load class {}. Proceeding without FML support.",
+ ex.getMessage());
+ }
+
+ return this.clCoreModManager;
+ }
+
/**
* Check whether a tweaker ending with tweakName has been enqueued
* but not yet visited.
@@ -373,19 +369,6 @@ private static boolean isTweakerQueued(String tweakerName) {
return false;
}
- /**
- * Attempt to get the FML CoreModManager, tries the post-1.8 namespace first
- * and falls back to 1.7.10 if class lookup fails
- */
- private static Class> getCoreModManagerClass() throws ClassNotFoundException {
- try {
- return Class.forName(GlobalProperties.getString(
- GlobalProperties.Keys.FML_CORE_MOD_MANAGER, MixinPlatformAgentFMLLegacy.CORE_MOD_MANAGER_CLASS));
- } catch (ClassNotFoundException ex) {
- return Class.forName(MixinPlatformAgentFMLLegacy.CORE_MOD_MANAGER_CLASS_LEGACY);
- }
- }
-
@SuppressWarnings("unchecked")
private static List getIgnoredMods(Class> clCoreModManager) throws IllegalAccessException, InvocationTargetException {
Method mdGetIgnoredMods = null;
@@ -412,7 +395,22 @@ private static List getIgnoredMods(Class> clCoreModManager) throws Ill
*/
@Override
public void init() {
- // Nothing to do here
+ if (this.getCoreModManagerClass() != null) {
+// MixinEnvironment.registerPhaseProvider(MixinPlatformAgentFMLLegacy.class.getName() + "$PhaseProvider");
+ this.injectRemapper();
+ }
+ }
+
+ private void injectRemapper() {
+ try {
+ MixinPlatformAgentAbstract.logger.debug("Creating FML remapper adapter: {}", MixinPlatformAgentFMLLegacy.FML_REMAPPER_ADAPTER_CLASS);
+ Class> clFmlRemapperAdapter = Class.forName(MixinPlatformAgentFMLLegacy.FML_REMAPPER_ADAPTER_CLASS, true, Launch.classLoader);
+ Method mdCreate = clFmlRemapperAdapter.getDeclaredMethod("create");
+ IRemapper remapper = (IRemapper)mdCreate.invoke(null);
+ MixinEnvironment.getDefaultEnvironment().getRemappers().add(remapper);
+ } catch (Exception ex) {
+ MixinPlatformAgentAbstract.logger.debug("Failed instancing FML remapper adapter, things will probably go horribly for notch-obf'd mods!");
+ }
}
/* (non-Javadoc)
diff --git a/src/launchwrapper/java/org/spongepowered/asm/service/mojang/MixinServiceLaunchWrapper.java b/src/launchwrapper/java/org/spongepowered/asm/service/mojang/MixinServiceLaunchWrapper.java
index 82a11fb5d..2ef4c8980 100644
--- a/src/launchwrapper/java/org/spongepowered/asm/service/mojang/MixinServiceLaunchWrapper.java
+++ b/src/launchwrapper/java/org/spongepowered/asm/service/mojang/MixinServiceLaunchWrapper.java
@@ -81,7 +81,7 @@ public class MixinServiceLaunchWrapper extends MixinServiceAbstract implements I
public static final Keys BLACKBOARD_KEY_TWEAKCLASSES = Keys.of("TweakClasses");
public static final Keys BLACKBOARD_KEY_TWEAKS = Keys.of("Tweaks");
- private static final String MIXIN_TWEAKER_CLASS = "org.spongepowered.asm.launch.MixinTweaker";
+ private static final String MIXIN_TWEAKER_CLASS = MixinServiceAbstract.LAUNCH_PACKAGE + "MixinTweaker";
// Consts
private static final String STATE_TWEAKER = MixinServiceAbstract.MIXIN_PACKAGE + "EnvironmentStateTweaker";
@@ -618,5 +618,5 @@ private static int findInStackTrace(String className, String methodName) {
return 0;
}
-
+
}
diff --git a/src/launchwrapper/java/org/spongepowered/asm/service/mojang/MixinServiceLaunchWrapperBootstrap.java b/src/launchwrapper/java/org/spongepowered/asm/service/mojang/MixinServiceLaunchWrapperBootstrap.java
index 0b1aaaf49..bdb726ce2 100644
--- a/src/launchwrapper/java/org/spongepowered/asm/service/mojang/MixinServiceLaunchWrapperBootstrap.java
+++ b/src/launchwrapper/java/org/spongepowered/asm/service/mojang/MixinServiceLaunchWrapperBootstrap.java
@@ -35,6 +35,7 @@
public class MixinServiceLaunchWrapperBootstrap implements IMixinServiceBootstrap {
private static final String SERVICE_PACKAGE = "org.spongepowered.asm.service.";
+ private static final String LAUNCH_PACKAGE = "org.spongepowered.asm.launch.";
private static final String MIXIN_UTIL_PACKAGE = "org.spongepowered.asm.util.";
private static final String LEGACY_ASM_PACKAGE = "org.spongepowered.asm.lib.";
@@ -61,7 +62,8 @@ public void bootstrap() {
// Essential ones
Launch.classLoader.addClassLoaderExclusion(MixinServiceLaunchWrapperBootstrap.SERVICE_PACKAGE);
-
+ Launch.classLoader.addClassLoaderExclusion(MixinServiceLaunchWrapperBootstrap.LAUNCH_PACKAGE);
+
// Important ones
Launch.classLoader.addClassLoaderExclusion(MixinServiceLaunchWrapperBootstrap.ASM_PACKAGE);
Launch.classLoader.addClassLoaderExclusion(MixinServiceLaunchWrapperBootstrap.LEGACY_ASM_PACKAGE);
diff --git a/src/main/java/org/spongepowered/asm/launch/MixinBootstrap.java b/src/main/java/org/spongepowered/asm/launch/MixinBootstrap.java
index 87067c653..4f6719100 100644
--- a/src/main/java/org/spongepowered/asm/launch/MixinBootstrap.java
+++ b/src/main/java/org/spongepowered/asm/launch/MixinBootstrap.java
@@ -24,6 +24,8 @@
*/
package org.spongepowered.asm.launch;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.LogManager;
@@ -32,6 +34,9 @@
import org.spongepowered.asm.launch.platform.MixinPlatformManager;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.asm.mixin.MixinEnvironment.Phase;
+import org.spongepowered.asm.mixin.throwables.MixinError;
+import org.spongepowered.asm.service.IMixinInternal;
+import org.spongepowered.asm.service.IMixinService;
import org.spongepowered.asm.service.MixinService;
/**
@@ -63,11 +68,17 @@ public abstract class MixinBootstrap {
*/
public static final String VERSION = "0.8.3";
+ /**
+ * Transformer factory
+ */
+ private static final String MIXIN_TRANSFORMER_FACTORY_CLASS = "org.spongepowered.asm.mixin.transformer.MixinTransformer$Factory";
+
/**
* Log all the things
*/
private static final Logger logger = LogManager.getLogger("mixin");
+
// These are Klass local, with luck this shouldn't be a problem
private static boolean initialised = false;
private static boolean initState = true;
@@ -77,7 +88,7 @@ public abstract class MixinBootstrap {
MixinService.boot();
MixinService.getService().prepare();
}
-
+
/**
* Platform manager instance
*/
@@ -134,6 +145,7 @@ static boolean start() {
}
MixinBootstrap.registerSubsystem(MixinBootstrap.VERSION);
+ MixinBootstrap.offerInternals();
if (!MixinBootstrap.initialised) {
MixinBootstrap.initialised = true;
@@ -207,4 +219,31 @@ private static void registerSubsystem(String version) {
GlobalProperties.put(GlobalProperties.Keys.INIT, version);
}
+ private static void offerInternals() {
+ IMixinService service = MixinService.getService();
+
+ try {
+ for (IMixinInternal internal : MixinBootstrap.getInternals()) {
+ service.offer(internal);
+ }
+ } catch (AbstractMethodError ex) {
+ // outdated service
+ ex.printStackTrace();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static List getInternals() throws MixinError {
+ List internals = new ArrayList();
+ try {
+ Class clTransformerFactory = (Class)Class.forName(MixinBootstrap.MIXIN_TRANSFORMER_FACTORY_CLASS);
+ Constructor ctor = clTransformerFactory.getDeclaredConstructor();
+ ctor.setAccessible(true);
+ internals.add(ctor.newInstance());
+ } catch (ReflectiveOperationException ex) {
+ throw new MixinError(ex);
+ }
+ return internals;
+ }
+
}
diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/IMixinTransformer.java b/src/main/java/org/spongepowered/asm/mixin/transformer/IMixinTransformer.java
index 183190c73..769ab93fc 100644
--- a/src/main/java/org/spongepowered/asm/mixin/transformer/IMixinTransformer.java
+++ b/src/main/java/org/spongepowered/asm/mixin/transformer/IMixinTransformer.java
@@ -52,6 +52,20 @@ public interface IMixinTransformer {
*/
public abstract List reload(String mixinClass, ClassNode classNode);
+ /**
+ * Called when the transformation reason is computing_frames. The only
+ * operation we care about here is adding interfaces to target classes but
+ * at the moment we don't have sufficient scaffolding to determine that
+ * without triggering re-entrance. Currently just a no-op in order to not
+ * cause a re-entrance crash under ModLauncher 7.0+.
+ *
+ * @param environment Current environment
+ * @param name Class transformed name
+ * @param classNode Class tree
+ * @return true if the class was transformed
+ */
+ public abstract boolean computeFramesForClass(MixinEnvironment environment, String name, ClassNode classNode);
+
/**
* Callback from the hotswap agent and LaunchWrapper Proxy, transform class
* bytecode. This method delegates to class generation or class
@@ -67,6 +81,43 @@ public interface IMixinTransformer {
* @see ILegacyClassTransformer#transformClassBytes(String, String, byte[])
*/
public abstract byte[] transformClassBytes(String name, String transformedName, byte[] basicClass);
+
+ /**
+ * Apply mixins and postprocessors to the supplied class
+ *
+ * @param environment Current environment
+ * @param name Class transformed name
+ * @param classBytes Class bytecode
+ * @return Transformed bytecode
+ */
+ public abstract byte[] transformClass(MixinEnvironment environment, String name, byte[] classBytes);
+
+ /**
+ * Apply mixins and postprocessors to the supplied class
+ *
+ * @param environment Current environment
+ * @param name Class transformed name
+ * @param classNode Class tree
+ * @return true if the class was transformed
+ */
+ public abstract boolean transformClass(MixinEnvironment environment, String name, ClassNode classNode);
+
+ /**
+ * Generate the specified mixin-synthetic class
+ *
+ * @param environment Current environment
+ * @param name Class name to generate
+ * @return Generated bytecode or null if no class was generated
+ */
+ public abstract byte[] generateClass(MixinEnvironment environment, String name);
+
+ /**
+ * @param environment Current environment
+ * @param name Class transformed name
+ * @param classNode Empty classnode to populate
+ * @return True if the class was generated successfully
+ */
+ public abstract boolean generateClass(MixinEnvironment environment, String name, ClassNode classNode);
/**
* Get the transformer extensions
diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/IMixinTransformerFactory.java b/src/main/java/org/spongepowered/asm/mixin/transformer/IMixinTransformerFactory.java
new file mode 100644
index 000000000..7e3b10ed8
--- /dev/null
+++ b/src/main/java/org/spongepowered/asm/mixin/transformer/IMixinTransformerFactory.java
@@ -0,0 +1,42 @@
+/*
+ * This file is part of Mixin, licensed under the MIT License (MIT).
+ *
+ * Copyright (c) SpongePowered
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package org.spongepowered.asm.mixin.transformer;
+
+import org.spongepowered.asm.launch.MixinInitialisationError;
+import org.spongepowered.asm.service.IMixinInternal;
+
+/**
+ * Factory for the mixin transformer, concrete instances of this class are only
+ * provided to services since only the service should be able to decide when the
+ * mixin transformer is initialised.
+ */
+public interface IMixinTransformerFactory extends IMixinInternal {
+
+ /**
+ * Create a new transformer.
+ */
+ public abstract IMixinTransformer createTransformer() throws MixinInitialisationError;
+
+}
diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinTransformer.java b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinTransformer.java
index a9b09c74f..183248c5d 100644
--- a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinTransformer.java
+++ b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinTransformer.java
@@ -28,6 +28,7 @@
import java.util.List;
import org.objectweb.asm.tree.ClassNode;
+import org.spongepowered.asm.launch.MixinInitialisationError;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.asm.mixin.MixinEnvironment.Option;
import org.spongepowered.asm.mixin.throwables.MixinException;
@@ -41,10 +42,26 @@
/**
* Transformer which manages the mixin configuration and application process
*/
-class MixinTransformer extends TreeTransformer implements IMixinTransformer {
+final class MixinTransformer extends TreeTransformer implements IMixinTransformer {
+
+ /**
+ * Impl of mixin transformer factory
+ */
+ static class Factory implements IMixinTransformerFactory {
+
+ /* (non-Javadoc)
+ * @see org.spongepowered.asm.mixin.transformer.IMixinTransformerFactory
+ * #createTransformer()
+ */
+ @Override
+ public IMixinTransformer createTransformer() throws MixinInitialisationError {
+ return new MixinTransformer();
+ }
+
+ }
private static final String MIXIN_AGENT_CLASS = "org.spongepowered.tools.agent.MixinAgent";
-
+
/**
* Synthetic class registry
*/
@@ -70,7 +87,7 @@ class MixinTransformer extends TreeTransformer implements IMixinTransformer {
*/
private final MixinClassGenerator generator;
- public MixinTransformer() {
+ MixinTransformer() {
MixinEnvironment environment = MixinEnvironment.getCurrentEnvironment();
Object globalMixinTransformer = environment.getActiveTransformer();
@@ -190,6 +207,7 @@ public byte[] transformClassBytes(String name, String transformedName, byte[] ba
* @param classNode Class tree
* @return true if the class was transformed
*/
+ @Override
public boolean computeFramesForClass(MixinEnvironment environment, String name, ClassNode classNode) {
// TODO compute added interfaces
return false;
@@ -203,6 +221,7 @@ public boolean computeFramesForClass(MixinEnvironment environment, String name,
* @param classBytes Class bytecode
* @return Transformed bytecode
*/
+ @Override
public byte[] transformClass(MixinEnvironment environment, String name, byte[] classBytes) {
ClassNode classNode = this.readClass(classBytes);
if (this.processor.applyMixins(environment, name, classNode)) {
@@ -219,6 +238,7 @@ public byte[] transformClass(MixinEnvironment environment, String name, byte[] c
* @param classNode Class tree
* @return true if the class was transformed
*/
+ @Override
public boolean transformClass(MixinEnvironment environment, String name, ClassNode classNode) {
return this.processor.applyMixins(environment, name, classNode);
}
@@ -230,6 +250,7 @@ public boolean transformClass(MixinEnvironment environment, String name, ClassNo
* @param name Class name to generate
* @return Generated bytecode or null if no class was generated
*/
+ @Override
public byte[] generateClass(MixinEnvironment environment, String name) {
ClassNode classNode = MixinTransformer.createEmptyClass(name);
if (this.generator.generateClass(environment, name, classNode)) {
@@ -244,6 +265,7 @@ public byte[] generateClass(MixinEnvironment environment, String name) {
* @param classNode Empty classnode to populate
* @return True if the class was generated successfully
*/
+ @Override
public boolean generateClass(MixinEnvironment environment, String name, ClassNode classNode) {
return this.generator.generateClass(environment, name, classNode);
}
diff --git a/src/main/java/org/spongepowered/asm/service/IMixinInternal.java b/src/main/java/org/spongepowered/asm/service/IMixinInternal.java
new file mode 100644
index 000000000..2e354fd90
--- /dev/null
+++ b/src/main/java/org/spongepowered/asm/service/IMixinInternal.java
@@ -0,0 +1,32 @@
+/*
+ * This file is part of Mixin, licensed under the MIT License (MIT).
+ *
+ * Copyright (c) SpongePowered
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package org.spongepowered.asm.service;
+
+/**
+ * A mixin internal part, offered to services.
+ */
+public interface IMixinInternal {
+
+}
diff --git a/src/main/java/org/spongepowered/asm/service/IMixinService.java b/src/main/java/org/spongepowered/asm/service/IMixinService.java
index aa5c324f6..a4f068c62 100644
--- a/src/main/java/org/spongepowered/asm/service/IMixinService.java
+++ b/src/main/java/org/spongepowered/asm/service/IMixinService.java
@@ -62,6 +62,15 @@ public interface IMixinService {
*/
public abstract Phase getInitialPhase();
+ /**
+ * Called when the subsystem is offering internal components to the service,
+ * the service can determine whether to retain or ignore the component based
+ * on its own requirements.
+ *
+ * @param internal Internal component being offered
+ */
+ public abstract void offer(IMixinInternal internal);
+
/**
* Called at the end of subsystem boot
*/
diff --git a/src/main/java/org/spongepowered/asm/service/MixinServiceAbstract.java b/src/main/java/org/spongepowered/asm/service/MixinServiceAbstract.java
index 9e57708a3..b5c6a2465 100644
--- a/src/main/java/org/spongepowered/asm/service/MixinServiceAbstract.java
+++ b/src/main/java/org/spongepowered/asm/service/MixinServiceAbstract.java
@@ -26,7 +26,9 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -50,6 +52,7 @@ public abstract class MixinServiceAbstract implements IMixinService {
// Consts
protected static final String LAUNCH_PACKAGE = "org.spongepowered.asm.launch.";
protected static final String MIXIN_PACKAGE = "org.spongepowered.asm.mixin.";
+ protected static final String SERVICE_PACKAGE = "org.spongepowered.asm.service.";
/**
* Logger
@@ -62,6 +65,11 @@ public abstract class MixinServiceAbstract implements IMixinService {
*/
protected final ReEntranceLock lock = new ReEntranceLock(1);
+ /**
+ * All internals offered to this service
+ */
+ private final Map, IMixinInternal> internals = new HashMap, IMixinInternal>();
+
/**
* Service agent instances
*/
@@ -104,20 +112,35 @@ public CompatibilityLevel getMinCompatibilityLevel() {
public CompatibilityLevel getMaxCompatibilityLevel() {
return null;
}
-
+
/* (non-Javadoc)
- * @see org.spongepowered.asm.service.IMixinService#beginPhase()
+ * @see org.spongepowered.asm.service.IMixinService
+ * #offer(org.spongepowered.asm.service.IMixinInternal)
*/
@Override
- public void beginPhase() {
+ public void offer(IMixinInternal internal) {
+ this.registerInternal(internal, internal.getClass());
+ }
+
+ @SuppressWarnings("unchecked")
+ private void registerInternal(IMixinInternal internal, Class> clazz) {
+ for (Class> iface : clazz.getInterfaces()) {
+ if (iface == IMixinInternal.class) {
+ this.internals.put((Class)clazz, internal);
+ }
+ this.registerInternal(internal, iface);
+ }
}
- /* (non-Javadoc)
- * @see org.spongepowered.asm.service.IMixinService
- * #checkEnv(java.lang.Object)
- */
- @Override
- public void checkEnv(Object bootSource) {
+ @SuppressWarnings("unchecked")
+ protected final T getInternal(Class type) {
+ for (Class internalType : this.internals.keySet()) {
+ if (type.isAssignableFrom(internalType)) {
+ return (T)this.internals.get(internalType);
+ }
+ }
+
+ return null;
}
/* (non-Javadoc)
@@ -130,6 +153,21 @@ public void init() {
}
}
+ /* (non-Javadoc)
+ * @see org.spongepowered.asm.service.IMixinService#beginPhase()
+ */
+ @Override
+ public void beginPhase() {
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongepowered.asm.service.IMixinService
+ * #checkEnv(java.lang.Object)
+ */
+ @Override
+ public void checkEnv(Object bootSource) {
+ }
+
/* (non-Javadoc)
* @see org.spongepowered.asm.service.IMixinService#getReEntranceLock()
*/
diff --git a/src/main/java/org/spongepowered/asm/util/Locals.java b/src/main/java/org/spongepowered/asm/util/Locals.java
index f57974a6f..0ae2e21da 100644
--- a/src/main/java/org/spongepowered/asm/util/Locals.java
+++ b/src/main/java/org/spongepowered/asm/util/Locals.java
@@ -454,7 +454,8 @@ public static List generateLocalVariableTable(ClassNode class
String desc = lastKnownType[j];
Type localType = local.getType();
if (localType != null) {
- desc = "null".equals(localType.getInternalName()) ? Constants.OBJECT_DESC : localType.getDescriptor();
+ desc = localType.getSort() >= Type.ARRAY && "null".equals(localType.getInternalName())
+ ? Constants.OBJECT_DESC : localType.getDescriptor();
}
localNodes[j] = new LocalVariableNode("var" + j, desc, null, label, null, j);
diff --git a/src/modlauncher/java/org/spongepowered/asm/service/modlauncher/MixinServiceModLauncher.java b/src/modlauncher/java/org/spongepowered/asm/service/modlauncher/MixinServiceModLauncher.java
index c7782f6e8..80791f9eb 100644
--- a/src/modlauncher/java/org/spongepowered/asm/service/modlauncher/MixinServiceModLauncher.java
+++ b/src/modlauncher/java/org/spongepowered/asm/service/modlauncher/MixinServiceModLauncher.java
@@ -31,11 +31,12 @@
import org.spongepowered.asm.launch.platform.container.ContainerHandleModLauncher;
import org.spongepowered.asm.mixin.MixinEnvironment.CompatibilityLevel;
import org.spongepowered.asm.mixin.MixinEnvironment.Phase;
-import org.spongepowered.asm.mixin.transformer.MixinTransformationHandler;
+import org.spongepowered.asm.mixin.transformer.IMixinTransformerFactory;
import org.spongepowered.asm.service.IClassBytecodeProvider;
import org.spongepowered.asm.service.IClassProvider;
import org.spongepowered.asm.service.IClassTracker;
import org.spongepowered.asm.service.IMixinAuditTrail;
+import org.spongepowered.asm.service.IMixinInternal;
import org.spongepowered.asm.service.ITransformerProvider;
import org.spongepowered.asm.service.MixinServiceAbstract;
import org.spongepowered.asm.util.IConsumer;
@@ -114,6 +115,14 @@ public void onInit(IClassBytecodeProvider bytecodeProvider) {
public void onStartup() {
this.phaseConsumer.accept(Phase.DEFAULT);
}
+
+ @Override
+ public void offer(IMixinInternal internal) {
+ if (internal instanceof IMixinTransformerFactory) {
+ this.getTransformationHandler().offer((IMixinTransformerFactory)internal);
+ }
+ super.offer(internal);
+ }
// TEMP
@SuppressWarnings("deprecation")
@@ -212,7 +221,7 @@ public IMixinAuditTrail getAuditTrail() {
/**
* Get (or create) the transformation handler
*/
- private IClassProcessor getTransformationHandler() {
+ private MixinTransformationHandler getTransformationHandler() {
if (this.transformationHandler == null) {
this.transformationHandler = new MixinTransformationHandler();
}
diff --git a/src/modlauncher/java/org/spongepowered/asm/mixin/transformer/MixinTransformationHandler.java b/src/modlauncher/java/org/spongepowered/asm/service/modlauncher/MixinTransformationHandler.java
similarity index 76%
rename from src/modlauncher/java/org/spongepowered/asm/mixin/transformer/MixinTransformationHandler.java
rename to src/modlauncher/java/org/spongepowered/asm/service/modlauncher/MixinTransformationHandler.java
index 303efd2e8..303e1c7e8 100644
--- a/src/modlauncher/java/org/spongepowered/asm/mixin/transformer/MixinTransformationHandler.java
+++ b/src/modlauncher/java/org/spongepowered/asm/service/modlauncher/MixinTransformationHandler.java
@@ -22,7 +22,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package org.spongepowered.asm.mixin.transformer;
+package org.spongepowered.asm.service.modlauncher;
import java.util.EnumSet;
@@ -32,9 +32,13 @@
import org.spongepowered.asm.launch.MixinLaunchPlugin;
import org.spongepowered.asm.launch.Phases;
import org.spongepowered.asm.mixin.MixinEnvironment;
+import org.spongepowered.asm.mixin.transformer.IMixinTransformer;
+import org.spongepowered.asm.mixin.transformer.IMixinTransformerFactory;
import org.spongepowered.asm.service.ISyntheticClassInfo;
import org.spongepowered.asm.service.ISyntheticClassRegistry;
+import com.google.common.base.Preconditions;
+
import cpw.mods.modlauncher.api.ITransformerActivity;
import cpw.mods.modlauncher.serviceapi.ILaunchPluginService.Phase;
@@ -43,16 +47,16 @@
* application, post processing and synthetic class generation
*/
public class MixinTransformationHandler implements IClassProcessor {
-
+
/**
- * Lock for initialising the transformer
+ * Mixin transformer factory, from service
*/
- private final Object initialisationLock = new Object();
+ private IMixinTransformerFactory transformerFactory;
/**
* Transformer pipeline instance
*/
- private MixinTransformer transformer;
+ private IMixinTransformer transformer;
/**
* Synthetic class registry, used so the processor knows when to respond to
@@ -60,6 +64,11 @@ public class MixinTransformationHandler implements IClassProcessor {
*/
private ISyntheticClassRegistry registry;
+ void offer(IMixinTransformerFactory transformerFactory) {
+ Preconditions.checkNotNull(transformerFactory, "transformerFactory");
+ this.transformerFactory = transformerFactory;
+ }
+
/* (non-Javadoc)
* @see org.spongepowered.asm.launch.IClassProcessor#handlesClass(
* org.objectweb.asm.Type, boolean, java.lang.String)
@@ -89,18 +98,13 @@ public synchronized boolean processClass(Phase phase, ClassNode classNode, Type
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();
- }
+ if (this.transformerFactory == null) {
+ throw new IllegalStateException("processClass called before transformer factory offered to transformation handler");
}
- } else {
- transformer = this.transformer;
+ this.transformer = this.transformerFactory.createTransformer();
+ this.registry = this.transformer.getExtensions().getSyntheticClassRegistry();
}
// Don't transform when the reason is mixin (side-loading in progress)
@@ -111,14 +115,14 @@ public synchronized boolean processClass(Phase phase, ClassNode classNode, Type
MixinEnvironment environment = MixinEnvironment.getCurrentEnvironment();
ISyntheticClassInfo syntheticClass = this.registry.findSyntheticClass(classType.getClassName());
if (syntheticClass != null) {
- return transformer.generateClass(environment, classType.getClassName(), classNode);
+ return this.transformer.generateClass(environment, classType.getClassName(), classNode);
}
if (ITransformerActivity.COMPUTING_FRAMES_REASON.equals(reason)) {
- return transformer.computeFramesForClass(environment, classType.getClassName(), classNode);
+ return this.transformer.computeFramesForClass(environment, classType.getClassName(), classNode);
}
- return transformer.transformClass(environment, classType.getClassName(), classNode);
+ return this.transformer.transformClass(environment, classType.getClassName(), classNode);
}
}