Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update MixinBooter #275

Open
wants to merge 3 commits into
base: experimental/foundation
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public class ForgeEarlyConfig {
public static String COCOA_FRAME_NAME = "minecraft";

public static String CONFIG_ANY_TIME_VERSION = "3.0";
public static String MIXIN_BOOTER_VERSION = "10.2";
public static String MIXIN_BOOTER_VERSION = "10.3";

@Config.Comment("""
Mods in this list have one or more of the problems list below:
Expand Down
57 changes: 43 additions & 14 deletions src/main/java/net/minecraftforge/fml/common/LoadController.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,15 @@
import net.minecraftforge.fml.relauncher.libraries.LibraryManager;
import org.apache.logging.log4j.ThreadContext;
import org.apache.logging.log4j.message.FormattedMessage;

import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.asm.mixin.Mixins;
import org.spongepowered.asm.mixin.ModUtil;
import org.spongepowered.asm.mixin.transformer.Proxy;
import org.spongepowered.asm.service.MixinService;
import org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper;
import org.spongepowered.asm.util.Constants;
import zone.rong.mixinbooter.Context;
import zone.rong.mixinbooter.ILateMixinLoader;

import javax.annotation.Nullable;
Expand Down Expand Up @@ -165,22 +168,43 @@ public void distributeStateMessage(LoaderState state, Object... eventData)

FMLContextQuery.init(); // Initialize FMLContextQuery and add it to the global list

// Load late mixins
FMLLog.log.info("Instantiating all ILateMixinLoader implemented classes...");
for (ASMDataTable.ASMData asmData : asmDataTable.getAll(ILateMixinLoader.class.getName().replace('.', '/'))) {
modClassLoader.addFile(asmData.getCandidate().getModContainer()); // Add to path before `newInstance`
Class<?> clazz = Class.forName(asmData.getClassName().replace('/', '.'));
FMLLog.log.info("Instantiating {} for its mixins.", clazz);
ILateMixinLoader loader = (ILateMixinLoader) clazz.getConstructor().newInstance();
for (String mixinConfig : loader.getMixinConfigs()) {
if (loader.shouldMixinConfigQueue(mixinConfig)) {
FMLLog.log.info("Adding {} mixin configuration.", mixinConfig);
try {
Mixins.addConfiguration(mixinConfig);
loader.onMixinConfigQueued(mixinConfig);
} catch (Throwable t) {
FMLLog.log.error("Error adding mixin configuration for {}", mixinConfig, t);
try {
modClassLoader.addFile(asmData.getCandidate().getModContainer()); // Add to path before `newInstance`
Class<?> clazz = Class.forName(asmData.getClassName().replace('/', '.'));
FMLLog.log.info("Instantiating {} for its mixins.", clazz);
@SuppressWarnings("deprecation")
ILateMixinLoader loader = (ILateMixinLoader) clazz.getConstructor().newInstance();
for (String mixinConfig : loader.getMixinConfigs()) {
@SuppressWarnings("deprecation")
Context context = new Context(mixinConfig);
if (loader.shouldMixinConfigQueue(context)) {
try {
FMLLog.log.info("Adding {} mixin configuration.", mixinConfig);
Mixins.addConfiguration(mixinConfig);
loader.onMixinConfigQueued(context);
} catch (Throwable t) {
FMLLog.log.error("Error adding mixin configuration for {}", mixinConfig, t);
}
}
}
} catch (ClassNotFoundException | ClassCastException | InstantiationException | IllegalAccessException e) {
FMLLog.log.error("Unable to load the ILateMixinLoader", e);
}
}

// mark config owners : for earlys, lates, and mfAttributes.
for (Config config : Mixins.getConfigs()) {
if (!config.getConfig().hasDecoration(ModUtil.OWNER_DECORATOR)) {
List<ModContainer> owners = getPackageOwners();
if (owners.isEmpty()) {
config.getConfig().decorate(ModUtil.OWNER_DECORATOR, (Supplier) () -> ModUtil.UNKNOWN_OWNER);
} else {
final String owner = owner.getFirst().getModId(); // TODO : better assign ?
config.getConfig().decorate(ModUtil.OWNER_DECORATOR, (Supplier) () -> owner);
}
}
}

Expand Down Expand Up @@ -421,15 +445,20 @@ private ModContainer findActiveContainerFromStack()
return StackWalker.getInstance()
.walk(frames -> frames.map(StackWalker.StackFrame::getClassName)
.filter(name -> name.lastIndexOf('.') != -1)
.map(name -> name.substring(0, name.lastIndexOf('.')))
.map(pkg -> packageOwners.get(pkg))
.map(name -> packageOwners.get(name.substring(0, name.lastIndexOf('.'))))
.filter(l -> !l.isEmpty())
.findFirst()
.map(List::getFirst)
.orElse(null)
);
}

@Nullable
public List<ModContainer> getPackageOwners(String pkg)
{
return packageOwners.get(pkg);
}

LoaderState getState()
{
return state;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@ public MixinContainer() {

@Override
public boolean registerBus(EventBus bus, LoadController controller) {
bus.register(this);
return true;
}

@Override
public File getSource()
{
public File getSource() {
return FMLSanityChecker.fmlLocation;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import net.minecraft.launchwrapper.LaunchClassLoader;
import net.minecraftforge.fml.relauncher.FMLLaunchHandler;
import org.apache.logging.log4j.LogManager;

import org.spongepowered.asm.launch.GlobalProperties;
import org.spongepowered.asm.launch.MixinBootstrap;

import java.io.File;
Expand All @@ -35,6 +37,7 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
Expand All @@ -55,6 +58,8 @@ public FMLTweaker()
MixinBootstrap.init();
LogManager.getLogger("FML.TWEAK").info("Initializing MixinExtras...");
MixinExtrasBootstrap.init();

GlobalProperties.put(GlobalProperties.Keys.CLEANROOM_DISABLE_MIXIN_CONFIGS, new HashSet<>());
}
@SuppressWarnings("unchecked")
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
import org.spongepowered.asm.mixin.Mixins;
import org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper;
import org.spongepowered.asm.util.Constants;
import zone.rong.mixinbooter.IEarlyMixinLoader;
import zone.rong.mixinbooter.IMixinConfigHijacker;

import java.io.*;
import java.net.MalformedURLException;
Expand Down Expand Up @@ -621,6 +623,7 @@ else if (deobfuscatedEnvironment && location == null) // This is probably a mod
FMLPluginWrapper wrap = new FMLPluginWrapper(coreModName, plugin, location, sortIndex, dependencies);
loadPlugins.add(wrap);
FMLLog.log.debug("Enqueued coremod {}", coreModName);
MixinBooterPlugin.loadEarlyMixinLoader(plugin);
return wrap;
}
catch (ClassNotFoundException cnfe)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
package net.minecraftforge.fml.relauncher;

import net.minecraft.launchwrapper.Launch;
import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.fml.common.FMLLog;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import org.spongepowered.asm.mixin.Mixins;
import zone.rong.mixinbooter.Context;
import zone.rong.mixinbooter.IEarlyMixinLoader;
import zone.rong.mixinbooter.IMixinConfigHijacker;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Collection;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Set;
import java.util.Map;

@SuppressWarnings("deprecation")
@IFMLLoadingPlugin.Name("MixinBooter")
@IFMLLoadingPlugin.MCVersion(ForgeVersion.mcVersion)
@IFMLLoadingPlugin.SortingIndex(1)
public final class MixinBooterPlugin implements IFMLLoadingPlugin {

static Set<IEarlyMixinLoader> earlyMixinLoaders = new HashSet<>();

public MixinBooterPlugin() {
}

Expand All @@ -38,38 +42,42 @@ public String getSetupClass() {

@Override
public void injectData(Map<String, Object> data) {
Object coremodList = data.get("coremodList");
if (coremodList instanceof List) {
Field fmlPluginWrapper$coreModInstance = null;
for (Object coremod : (List) coremodList) {
try {
if (fmlPluginWrapper$coreModInstance == null) {
fmlPluginWrapper$coreModInstance = coremod.getClass().getField("coreModInstance");
fmlPluginWrapper$coreModInstance.setAccessible(true);
}
Object theMod = fmlPluginWrapper$coreModInstance.get(coremod);
if (theMod instanceof IEarlyMixinLoader loader) {
FMLLog.log.info("Grabbing {} for its mixins.", loader.getClass());
for (String mixinConfig : loader.getMixinConfigs()) {
if (loader.shouldMixinConfigQueue(mixinConfig)) {
FMLLog.log.info("Adding {} mixin configuration.", mixinConfig);
Mixins.addConfiguration(mixinConfig);
loader.onMixinConfigQueued(mixinConfig);;
}
}
}
} catch (Throwable t) {
FMLLog.log.error("Unexpected error handling early mixins", t);
}
}
}
loadEarlyLoaders(earlyMixinLoaders);
earlyMixinLoaders = null;
}

@Override
public String getAccessTransformerClass() {
return null;
}

static void queneEarlyMixinLoader(IFMLLoadingPlugin plugin) {
if (plugin instanceof IEarlyMixinLoader earlyMixinLoader) earlyMixinLoaders.add(earlyMixinLoader);
if (plugin instanceof IMixinConfigHijacker hijacker) {
Collection<String> disabledConfigs = GlobalProperties.get(GlobalProperties.Keys.CLEANROOM_DISABLE_MIXIN_CONFIGS);
Context context = new Context(null);
FMLLog.log.info("Loading config hijacker {}.", interceptor.getClass().getName());
for (String hijacked : interceptor.getHijackedMixinConfigs(context)) {
disabledConfigs.add(hijacked);
FMLLog.log.info("{} will hijack the mixin config {}", interceptor.getClass().getName(), hijacked);
}
}
}

private void loadEarlyLoaders(Collection<IEarlyMixinLoader> queuedLoaders) {
for (IEarlyMixinLoader queuedLoader : queuedLoaders) {
FMLLog.log.info("Loading early loader {} for its mixins.", queuedLoader.getClass().getName());
for (String mixinConfig : queuedLoader.getMixinConfigs()) {
Context context = new Context(mixinConfig);
if (queuedLoader.shouldMixinConfigQueue(context)) {
FMLLog.log.info("Adding {} mixin configuration.", mixinConfig);
Mixins.addConfiguration(mixinConfig);
queuedLoader.onMixinConfigQueued(context);
}
}
}
}



}
79 changes: 79 additions & 0 deletions src/main/java/zone/rong/mixinbooter/Context.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package zone.rong.mixinbooter;

import net.minecraft.launchwrapper.Launch;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.relauncher.FMLLaunchHandler;

import java.util.Collection;

/**
* This class contains loading context for callers
*
*
* @since 10.0
* @deprecated We forked Mixin.
* <br>New approach:
* Check <a href=https://github.com/CleanroomMC/Fugue/tree/master>Fugue</a>.<br>
* Summary:<br>
* If you are coremod, just call {@link org.spongepowered.asm.mixin.Mixins#addConfigurations(String...)} in loadingPluging or Tweaker, and handle shouldApply in IMixinConfigPlugin<br>
* If you aren't coremod:<br>
* Group mixins by phase, add target env in config, use @env(MOD) for mod mixins.<br>
* Add {"MixinConfigs": "modid.mod.mixin.json,modid.default.mixin.json"} to your jar manifest.<br>
* Handle shouldApply in IMixinConfigPlugin. You can call {@link net.minecraftforge.fml.common.Loader#isModLoaded(String)} for {@link org.spongepowered.asm.mixin.MixinEnvironment.Phase#MOD} mixin.<br>
* Recommend to group target mod name by package name. You can also get config instance from {@link org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin#injectConfig(org.spongepowered.asm.mixin.transformer.Config)}.
*/
@Deprecated
public final class Context {

public enum ModLoader {
FORGE,
CLEANROOM;
}

private final String mixinConfig;

public Context(String mixinConfig, Collection<String> presentMods) {
this(mixinConfig); // TODO : better presentMods scan?
}

public Context(String mixinConfig) {
this.mixinConfig = mixinConfig;
}

/**
* @return the current mod loader
*/
public ModLoader modLoader() {
return ModLoader.CLEANROOM;
}

/**
* @return if the current environment is in-dev
*/
public boolean inDev() {
return FMLLaunchHandler.isDeobfuscatedEnvironment();
}

/**
* @return name of the mixin config that is currently being processed
*/
public String mixinConfig() {
return mixinConfig;
}

/**
* <p>For early contexts, the list of mods are gathered from culling the classloader
* for any jars that has the mcmod.info file. The mod IDs are obtained from the mcmod.info file.
* This means mostly, if not only coremods are queryable here,
* make sure to test a normal mod's existence in your mixin plugin or in the mixin itself.</p>
*
* <p>For late contexts, it comes from {@link net.minecraftforge.fml.common.Loader#getActiveModList}
* akin to {@link net.minecraftforge.fml.common.Loader#isModLoaded(String)}</p>
* @param modId to check against the list of present mods in the context
* @return whether the mod is present
*/
public boolean isModPresent(String modId) {
return Launch.classLoader.isClassLoaded("net.minecraftforge.fml.common.Loader") && Loader.isModLoaded(modId);
}

}
Loading
Loading