Skip to content

Commit

Permalink
Mixin changes (#31)
Browse files Browse the repository at this point in the history
* Rework mixin handling - now an array in META-INF/mixinconfigs.json

* Defer mixin configuration loading to mixin init phase 2 (agent prepare)

* Update licenses

* Add both mods from loading list and gamelibraries to GAME layer

* Let mixins be defined in mods.toml instead

* Gradlew
  • Loading branch information
Technici4n authored Nov 2, 2023
1 parent 3eaf250 commit 5836277
Show file tree
Hide file tree
Showing 14 changed files with 156 additions and 18 deletions.
4 changes: 2 additions & 2 deletions LICENSE-header.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Copyright (c) Forge Development LLC and contributors
SPDX-License-Identifier: LGPL-2.1-only
Copyright (c) NeoForged and contributors
SPDX-License-Identifier: LGPL-2.1-only
7 changes: 4 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
plugins {
id 'com.github.ben-manes.versions' version '0.39.0'
id 'org.javamodularity.moduleplugin' version '1.8.7'
id 'org.cadixdev.licenser' version '0.6.0'
id 'net.neoforged.licenser' version '0.7.2' apply false
id 'net.neoforged.gradleutils' version '[2.0.18,3)'
}

Expand All @@ -17,7 +17,7 @@ allprojects {

apply plugin: 'com.github.ben-manes.versions'
apply plugin: 'org.javamodularity.moduleplugin'
apply plugin: 'org.cadixdev.licenser'
apply plugin: 'net.neoforged.licenser'
apply plugin: 'net.neoforged.gradleutils'

group = 'net.neoforged.fancymodloader'
Expand Down Expand Up @@ -84,6 +84,7 @@ subprojects { subProject ->

license {
header = rootProject.file('LICENSE-header.txt')
skipExistingHeaders true

include 'net/neoforged/'
}
Expand Down Expand Up @@ -117,4 +118,4 @@ subprojects { subProject ->
changelog {
fromTag "1.0"
}
}
}
3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ modlauncher_version=10.0.9
securejarhandler_version=2.1.10
bootstraplauncher_version=1.1.2
asm_version=9.5
mixin_version=0.8.5
terminalconsoleappender_version=1.2.0
nightconfig_version=3.6.4
jetbrains_annotations_version=24.0.1
Expand All @@ -23,4 +24,4 @@ guava_version=31.1-jre
gson_version=2.10
apache_commons_lang3_version=3.12.0
jopt_simple_version=5.0.4
commons_io_version=2.11.0
commons_io_version=2.11.0
1 change: 1 addition & 0 deletions loader/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ dependencies {
implementation("net.sf.jopt-simple:jopt-simple:${jopt_simple_version}")
implementation("cpw.mods:securejarhandler:${securejarhandler_version}")
implementation("net.neoforged:accesstransformers:${accesstransformers_version}")
implementation("org.spongepowered:mixin:${mixin_version}")
implementation("net.minecrell:terminalconsoleappender:${terminalconsoleappender_version}")

implementation("org.apache.logging.log4j:log4j-core:${log4j_version}")
Expand Down
8 changes: 6 additions & 2 deletions loader/src/main/java/net/neoforged/fml/loading/FMLLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import com.mojang.logging.LogUtils;
import cpw.mods.modlauncher.Launcher;
import cpw.mods.modlauncher.api.*;
import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
import cpw.mods.modlauncher.util.ServiceLoaderUtils;
import net.neoforged.fml.loading.mixin.DeferredMixinConfigRegistration;
import net.neoforged.fml.loading.moddiscovery.BackgroundScanHandler;
import net.neoforged.fml.loading.moddiscovery.ModDiscoverer;
import net.neoforged.fml.loading.moddiscovery.ModFile;
Expand Down Expand Up @@ -157,11 +157,15 @@ public static List<ITransformationService.Resource> beginModScan(final Map<Strin
return List.of(pluginResources);
}

public static List<ITransformationService.Resource> completeScan(IModuleLayerManager layerManager) {
public static List<ITransformationService.Resource> completeScan(IModuleLayerManager layerManager, List<String> extraMixinConfigs) {
moduleLayerManager = layerManager;
languageLoadingProvider = new LanguageLoadingProvider();
backgroundScanHandler = modValidator.stage2Validation();
loadingModList = backgroundScanHandler.getLoadingModList();
if (loadingModList.getErrors().isEmpty()) {
// Add extra mixin configs
extraMixinConfigs.forEach(DeferredMixinConfigRegistration::addMixinConfig);
}
return List.of(modValidator.getModResources());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class FMLServiceProvider implements ITransformationService
private ArgumentAcceptingOptionSpec<String> modsOption;
private ArgumentAcceptingOptionSpec<String> modListsOption;
private ArgumentAcceptingOptionSpec<String> mavenRootsOption;
private ArgumentAcceptingOptionSpec<String> mixinConfigsOption;
private ArgumentAcceptingOptionSpec<String> fmlOption;
private ArgumentAcceptingOptionSpec<String> forgeOption;
private ArgumentAcceptingOptionSpec<String> mcOption;
Expand All @@ -38,6 +39,7 @@ public class FMLServiceProvider implements ITransformationService
private List<String> modsArgumentList;
private List<String> modListsArgumentList;
private List<String> mavenRootsArgumentList;
private List<String> mixinConfigsArgumentList;
private String targetForgeVersion;
private String targetFMLVersion;
private String targetMcVersion;
Expand Down Expand Up @@ -88,7 +90,7 @@ public List<Resource> beginScanning(final IEnvironment environment) {

@Override
public List<Resource> completeScan(final IModuleLayerManager layerManager) {
return FMLLoader.completeScan(layerManager);
return FMLLoader.completeScan(layerManager, mixinConfigsArgumentList);
}

@Override
Expand All @@ -111,6 +113,7 @@ public void arguments(BiFunction<String, String, OptionSpecBuilder> argumentBuil
modsOption = argumentBuilder.apply("mods", "List of mods to add").withRequiredArg().ofType(String.class).withValuesSeparatedBy(",");
modListsOption = argumentBuilder.apply("modLists", "JSON modlists").withRequiredArg().ofType(String.class).withValuesSeparatedBy(",");
mavenRootsOption = argumentBuilder.apply("mavenRoots", "Maven root directories").withRequiredArg().ofType(String.class).withValuesSeparatedBy(",");
mixinConfigsOption = argumentBuilder.apply("mixinConfig", "Additional mixin config files to load").withRequiredArg().ofType(String.class);
}

@Override
Expand All @@ -119,6 +122,7 @@ public void argumentValues(OptionResult option)
modsArgumentList = option.values(modsOption);
modListsArgumentList = option.values(modListsOption);
mavenRootsArgumentList = option.values(mavenRootsOption);
mixinConfigsArgumentList = option.values(mixinConfigsOption);
targetFMLVersion = option.value(fmlOption);
targetForgeVersion = option.value(forgeOption);
targetMcVersion = option.value(mcOption);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package net.neoforged.fml.loading;

import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
import net.neoforged.fml.loading.mixin.DeferredMixinConfigRegistration;
import net.neoforged.fml.loading.moddiscovery.BackgroundScanHandler;
import net.neoforged.fml.loading.moddiscovery.ModFile;
import net.neoforged.fml.loading.moddiscovery.ModFileInfo;
Expand Down Expand Up @@ -76,6 +77,14 @@ public void addCoreMods()
.forEach(FMLLoader.getCoreModProvider()::addCoreMod);
}

public void addMixinConfigs() {
modFiles.stream()
.map(ModFileInfo::getFile)
.map(ModFile::getMixinConfigs)
.flatMap(List::stream)
.forEach(DeferredMixinConfigRegistration::addMixinConfig);
}

public void addAccessTransformers()
{
modFiles.stream()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) NeoForged and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/

package net.neoforged.fml.loading.mixin;

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

import java.util.ArrayList;
import java.util.List;

public class DeferredMixinConfigRegistration {
private static boolean added = false;
private static final List<String> mixinConfigs = new ArrayList<>();

static {
// Register our platform agent first
List<String> agentClassNames = GlobalProperties.get(GlobalProperties.Keys.AGENTS);
agentClassNames.add(FMLMixinPlatformAgent.class.getName());
// Register the container (will use the platform agent)
MixinBootstrap.getPlatform().addContainer(new FMLMixinContainerHandle());
}

public static void addMixinConfig(String config) {
if (added) {
throw new IllegalStateException("Too late to add mixin configs!");
}

mixinConfigs.add(config);
}

static void registerConfigs() {
added = true;
mixinConfigs.forEach(Mixins::addConfiguration);
mixinConfigs.clear();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) NeoForged and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/

package net.neoforged.fml.loading.mixin;

import org.spongepowered.asm.launch.platform.container.IContainerHandle;

import java.util.Collection;
import java.util.List;

/**
* Container handle representing all of FML's mixin configs.
* No attribute because we directly load the mixin configs in {@link FMLMixinPlatformAgent}.
*/
public class FMLMixinContainerHandle implements IContainerHandle {
@Override
public String getAttribute(String name) {
return null;
}

@Override
public Collection<IContainerHandle> getNestedContainers() {
return List.of();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) NeoForged and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/

package net.neoforged.fml.loading.mixin;

import org.spongepowered.asm.launch.platform.MixinPlatformAgentAbstract;
import org.spongepowered.asm.launch.platform.MixinPlatformManager;
import org.spongepowered.asm.launch.platform.container.IContainerHandle;

public class FMLMixinPlatformAgent extends MixinPlatformAgentAbstract {
@Override
public AcceptResult accept(MixinPlatformManager manager, IContainerHandle handle) {
if (handle instanceof FMLMixinContainerHandle) {
return AcceptResult.ACCEPTED;
}
return AcceptResult.REJECTED;
}

@Override
public void prepare() {
// Load all the mixin configs!!
DeferredMixinConfigRegistration.registerConfigs();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,10 @@ private enum ScanStatus {
private final List<ModFile> pendingFiles;
private final List<ModFile> scannedFiles;
private final List<ModFile> allFiles;
private final List<ModFile> modFiles;
private ScanStatus status;
private LoadingModList loadingModList;

public BackgroundScanHandler(final List<ModFile> modFiles) {
this.modFiles = modFiles;
public BackgroundScanHandler() {
modContentScanner = Executors.newSingleThreadExecutor(r -> {
final Thread thread = Executors.defaultThreadFactory().newThread(r);
thread.setDaemon(true);
Expand All @@ -52,10 +50,6 @@ public BackgroundScanHandler(final List<ModFile> modFiles) {
status = ScanStatus.NOT_STARTED;
}

public List<ModFile> getModFiles() {
return modFiles;
}

public void submitForScanning(final ModFile file) {
if (modContentScanner.isShutdown()) {
status = ScanStatus.ERRORED;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public class ModFile implements IModFile {
private ModFileScanData fileModFileScanData;
private CompletableFuture<ModFileScanData> futureScanResult;
private List<CoreModFile> coreMods;
private List<String> mixinConfigs;
private Path accessTransformer;

static final Attributes.Name TYPE = new Attributes.Name("FMLModType");
Expand Down Expand Up @@ -112,6 +113,8 @@ public boolean identifyMods() {
LOGGER.debug(LogMarkers.LOADING,"Loading mod file {} with languages {}", this.getFilePath(), this.modFileInfo.requiredLanguageLoaders());
this.coreMods = ModFileParser.getCoreMods(this);
this.coreMods.forEach(mi-> LOGGER.debug(LogMarkers.LOADING,"Found coremod {}", mi.getPath()));
this.mixinConfigs = ModFileParser.getMixinConfigs(this.modFileInfo);
this.mixinConfigs.forEach(mc -> LOGGER.debug(LogMarkers.LOADING,"Found mixin config {}", mc));
this.accessTransformer = findResource("META-INF", "accesstransformer.cfg");
return true;
}
Expand All @@ -120,6 +123,10 @@ public List<CoreModFile> getCoreMods() {
return coreMods;
}

public List<String> getMixinConfigs() {
return mixinConfigs;
}

/**
* Run in an executor thread to harvest the class and annotation list
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,21 @@ protected static List<CoreModFile> getCoreMods(final ModFile modFile) {
.map(e -> new CoreModFile(e.getKey(), modFile.findResource(e.getValue()),modFile))
.toList();
}

protected static List<String> getMixinConfigs(IModFileInfo modFileInfo) {
try {
var config = modFileInfo.getConfig();
var mixinsEntries = config.getConfigList("mixins");
return mixinsEntries
.stream()
.map(entry -> entry
.<String>getConfigElement("config")
.orElseThrow(
() -> new InvalidModFileException("Missing \"config\" in [[mixins]] entry", modFileInfo)))
.toList();
} catch (Exception exception) {
LOGGER.error("Failed to load mixin configs from mod file", exception);
return List.of();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ModValidator {
private static final Logger LOGGER = LogUtils.getLogger();
Expand Down Expand Up @@ -71,7 +72,12 @@ public ITransformationService.Resource getPluginResources() {
}

public ITransformationService.Resource getModResources() {
return new ITransformationService.Resource(IModuleLayerManager.Layer.GAME, this.candidateMods.stream().map(IModFile::getSecureJar).toList());
var modFilesToLoad = Stream.concat(
// mods
this.loadingModList.getModFiles().stream().map(ModFileInfo::getFile),
// game libraries
this.modFiles.get(IModFile.Type.GAMELIBRARY).stream());
return new ITransformationService.Resource(IModuleLayerManager.Layer.GAME, modFilesToLoad.map(ModFile::getSecureJar).toList());
}

private List<EarlyLoadingException.ExceptionData> validateLanguages() {
Expand All @@ -97,8 +103,9 @@ public BackgroundScanHandler stage2Validation() {
loadingModList = ModSorter.sort(candidateMods, allErrors);
loadingModList.addCoreMods();
loadingModList.addAccessTransformers();
loadingModList.addMixinConfigs();
loadingModList.setBrokenFiles(brokenFiles);
BackgroundScanHandler backgroundScanHandler = new BackgroundScanHandler(candidateMods);
BackgroundScanHandler backgroundScanHandler = new BackgroundScanHandler();
loadingModList.addForScanning(backgroundScanHandler);
return backgroundScanHandler;
}
Expand Down

0 comments on commit 5836277

Please sign in to comment.