Better Mixin AP configuration (#423)
* [SPON-15] Apply Mixin AP config for all projects.
* Revert "[SPON-15] Apply Mixin AP config for all projects."
This reverts commit 93576e83b1221949d551b6307938f7dd6dc8fbbe.
* use setter & getter
* fix broken test introduced in 54d6ef7896
* initial commit for mixin extension
* refactor getConfiguration
* apply mixin extension
* [SPON-15] allow across project AP config
* [SPON-15] revert some changes
* [SPON-15] refactor codes
* [SPON-15] fix bugs
* [SPON-15] bring back cross-project apconfig
* [SPON-15] bug fix: move add default sourceSet earlier
* [SPON-15] fix style
* [SPON-15] refactor MixinAPExtension
* add test
* update test
* [SPON-15] fix test
* Update MixinAnnotationProcessorExtension.java
* [SPON-15] fix test
* fix deprecated gradle API
* [SPON-15] refactor ApInvoker
* [SPON-15] refactor ApInvoker
* allow change refmap name in sourceSet bases
* add new condition on test
* [SPON-15] fix wrong suffix
* Revert "[SPON-15] fix wrong suffix"
This reverts commit 98910392d91c26cd0454cca8cfc03c4e3d417fd6.
* fix mixinjson suffix
* use stream instead of collection for mixin json name
* change name for function
* use correct auto-refmap
* fix file name
* add with action
* add test
* refactor some codes
* refactor code
* update test
* fix checkstyle
* better error message
* fix checkstyle
* remove corss project option
* allow mixin inside loom
* remove project0
I should remove all project0. If I forget one please tell me.
* move `mixin` inside `loom`
* fix spotless
* merge attempt
* fix checkstyle
* seperate api & impl
* add experimental annotation for API
* use API
* Fix indentation
Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>
* fix typo
Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>
* fix typo
Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>
* better javadoc
Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>
			
			
This commit is contained in:
		
							parent
							
								
									b4ac68825f
								
							
						
					
					
						commit
						81fa551382
					
				
					 43 changed files with 1342 additions and 104 deletions
				
			
		|  | @ -44,6 +44,7 @@ import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | |||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; | ||||
| import net.fabricmc.loom.extension.LoomFiles; | ||||
| import net.fabricmc.loom.extension.LoomGradleExtensionImpl; | ||||
| import net.fabricmc.loom.extension.MixinApExtension; | ||||
| 
 | ||||
| public interface LoomGradleExtension extends LoomGradleExtensionAPI { | ||||
| 	static LoomGradleExtension get(Project project) { | ||||
|  | @ -102,4 +103,6 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI { | |||
| 		// TODO reimplement a way to change this, was never really supported api anyway | ||||
| 		return String.format("https://maven.fabricmc.net/net/fabricmc/intermediary/%1$s/intermediary-%1$s-v2.jar", minecraftVersion); | ||||
| 	} | ||||
| 
 | ||||
| 	MixinApExtension getMixinApExtension(); | ||||
| } | ||||
|  |  | |||
|  | @ -31,6 +31,7 @@ import org.gradle.api.Action; | |||
| import org.gradle.api.NamedDomainObjectContainer; | ||||
| import org.gradle.api.artifacts.Dependency; | ||||
| import org.gradle.api.file.ConfigurableFileCollection; | ||||
| import org.jetbrains.annotations.ApiStatus; | ||||
| 
 | ||||
| import net.fabricmc.loom.api.decompilers.LoomDecompiler; | ||||
| import net.fabricmc.loom.configuration.ide.RunConfigSettings; | ||||
|  | @ -81,6 +82,9 @@ public interface LoomGradleExtensionAPI { | |||
| 
 | ||||
| 	NamedDomainObjectContainer<RunConfigSettings> getRunConfigs(); | ||||
| 
 | ||||
| 	@ApiStatus.Experimental | ||||
| 	void mixin(Action<MixinApExtensionAPI> action); | ||||
| 
 | ||||
| 	void setCustomManifest(String customManifest); | ||||
| 
 | ||||
| 	String getCustomManifest(); | ||||
|  |  | |||
							
								
								
									
										92
									
								
								src/main/java/net/fabricmc/loom/api/MixinApExtensionAPI.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/main/java/net/fabricmc/loom/api/MixinApExtensionAPI.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,92 @@ | |||
| /* | ||||
|  * This file is part of fabric-loom, licensed under the MIT License (MIT). | ||||
|  * | ||||
|  * Copyright (c) 2021 FabricMC | ||||
|  * | ||||
|  * 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 net.fabricmc.loom.api; | ||||
| 
 | ||||
| import org.gradle.api.Action; | ||||
| import org.gradle.api.tasks.SourceSet; | ||||
| import org.gradle.api.tasks.util.PatternSet; | ||||
| import org.jetbrains.annotations.ApiStatus; | ||||
| 
 | ||||
| @ApiStatus.Experimental | ||||
| public interface MixinApExtensionAPI { | ||||
| 	/** | ||||
| 	 * Apply Mixin AP to sourceSet. | ||||
| 	 * @param sourceSet the sourceSet that applies Mixin AP. | ||||
| 	 * @param refmapName the output ref-map name. By default this will | ||||
| 	 *                      be {@link net.fabricmc.loom.LoomGradleExtension#getRefmapName()} | ||||
| 	 * @param action used for filter the mixin json files. By default this will be all files | ||||
| 	 *                  with name {@code *.mixins.json} that is inside the {@code resources} folder | ||||
| 	 *                  of {@code sourceSet}. | ||||
| 	 */ | ||||
| 	void add(SourceSet sourceSet, String refmapName, Action<PatternSet> action); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Apply Mixin AP to sourceSet. See {@link MixinApExtensionAPI#add(SourceSet, String, Action)} for more detail. | ||||
| 	 * @param sourceSet the sourceSet that applies Mixin AP. | ||||
| 	 * @param refmapName the output ref-map name. | ||||
| 	 */ | ||||
| 	void add(SourceSet sourceSet, String refmapName); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Apply Mixin AP to sourceSet. See {@link MixinApExtensionAPI#add(SourceSet, String, Action)} for more detail. | ||||
| 	 * @param sourceSet the sourceSet that applies Mixin AP. | ||||
| 	 * @param action used for filter the mixin json files. | ||||
| 	 */ | ||||
| 	void add(SourceSet sourceSet, Action<PatternSet> action); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Apply Mixin AP to sourceSet. See {@link MixinApExtensionAPI#add(SourceSet, String, Action)} for more detail. | ||||
| 	 * @param sourceSet the sourceSet that applies Mixin AP. | ||||
| 	 */ | ||||
| 	void add(SourceSet sourceSet); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Apply Mixin AP to sourceSet. See {@link MixinApExtensionAPI#add(SourceSet, String, Action)} for more detail. | ||||
| 	 * @param sourceSetName the name of sourceSet that applies Mixin AP. | ||||
| 	 * @param refmapName the output ref-map name. | ||||
| 	 * @param action used for filter the mixin json files. | ||||
| 	 */ | ||||
| 	void add(String sourceSetName, String refmapName, Action<PatternSet> action); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Apply Mixin AP to sourceSet. See {@link MixinApExtensionAPI#add(SourceSet, String, Action)} for more detail. | ||||
| 	 * @param sourceSetName the name of sourceSet that applies Mixin AP. | ||||
| 	 * @param refmapName the output ref-map name. | ||||
| 	 */ | ||||
| 	void add(String sourceSetName, String refmapName); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Apply Mixin AP to sourceSet. See {@link MixinApExtensionAPI#add(SourceSet, String, Action)} for more detail. | ||||
| 	 * @param sourceSetName the name of sourceSet that applies Mixin AP. | ||||
| 	 * @param action used for filter the mixin json files. | ||||
| 	 */ | ||||
| 	void add(String sourceSetName, Action<PatternSet> action); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Apply Mixin AP to sourceSet. See {@link MixinApExtensionAPI#add(SourceSet, String, Action)} for more detail. | ||||
| 	 * @param sourceSetName the name of sourceSet that applies Mixin AP. | ||||
| 	 */ | ||||
| 	void add(String sourceSetName); | ||||
| } | ||||
|  | @ -25,71 +25,47 @@ | |||
| package net.fabricmc.loom.build; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStreamReader; | ||||
| import java.nio.file.Path; | ||||
| import java.util.HashSet; | ||||
| import java.util.Set; | ||||
| import java.util.Objects; | ||||
| import java.util.stream.Stream; | ||||
| import java.util.zip.ZipEntry; | ||||
| 
 | ||||
| import com.google.gson.JsonObject; | ||||
| import org.gradle.api.Project; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| import org.zeroturnaround.zip.transform.StringZipEntryTransformer; | ||||
| import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.LoomGradlePlugin; | ||||
| import net.fabricmc.loom.extension.MixinApExtension; | ||||
| 
 | ||||
| public final class MixinRefmapHelper { | ||||
| 	private MixinRefmapHelper() { } | ||||
| 
 | ||||
| 	public static boolean addRefmapName(String filename, Path outputPath) { | ||||
| 	public static boolean addRefmapName(Project project, Path outputPath) { | ||||
| 		MixinApExtension mixin = LoomGradleExtension.get(project).getMixinApExtension(); | ||||
| 		File output = outputPath.toFile(); | ||||
| 		Set<String> mixinFilenames = findMixins(output, true); | ||||
| 
 | ||||
| 		if (mixinFilenames.size() > 0) { | ||||
| 			return ZipUtil.transformEntries(output, mixinFilenames.stream().map((f) -> new ZipEntryTransformerEntry(f, new StringZipEntryTransformer("UTF-8") { | ||||
| 		return mixin.getMixinSourceSetsStream().map(sourceSet -> { | ||||
| 			MixinApExtension.MixinInformationContainer container = Objects.requireNonNull( | ||||
| 					MixinApExtension.getMixinInformationContainer(sourceSet) | ||||
| 			); | ||||
| 			Stream<String> mixinJsonNames = container.getMixinJsonNames(); | ||||
| 			String refmapName = container.getRefmapName(); | ||||
| 
 | ||||
| 			return ZipUtil.transformEntries(output, mixinJsonNames.map(f -> new ZipEntryTransformerEntry(f, new StringZipEntryTransformer("UTF-8") { | ||||
| 				@Override | ||||
| 				protected String transform(ZipEntry zipEntry, String input) throws IOException { | ||||
| 				protected String transform(ZipEntry zipEntry, String input) { | ||||
| 					JsonObject json = LoomGradlePlugin.GSON.fromJson(input, JsonObject.class); | ||||
| 
 | ||||
| 					if (!json.has("refmap")) { | ||||
| 						json.addProperty("refmap", filename); | ||||
| 						json.addProperty("refmap", refmapName); | ||||
| 					} | ||||
| 
 | ||||
| 					return LoomGradlePlugin.GSON.toJson(json); | ||||
| 				} | ||||
| 			})).toArray(ZipEntryTransformerEntry[]::new)); | ||||
| 		} else { | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private static Set<String> findMixins(File output, boolean onlyWithoutRefmap) { | ||||
| 		// first, identify all of the mixin files | ||||
| 		Set<String> mixinFilename = new HashSet<>(); | ||||
| 		// TODO: this is a lovely hack | ||||
| 		ZipUtil.iterate(output, (stream, entry) -> { | ||||
| 			if (!entry.isDirectory() && entry.getName().endsWith(".json") && !entry.getName().contains("/") && !entry.getName().contains("\\")) { | ||||
| 				// JSON file in root directory | ||||
| 				try (InputStreamReader inputStreamReader = new InputStreamReader(stream)) { | ||||
| 					JsonObject json = LoomGradlePlugin.GSON.fromJson(inputStreamReader, JsonObject.class); | ||||
| 
 | ||||
| 					if (json != null) { | ||||
| 						boolean hasMixins = json.has("mixins") && json.get("mixins").isJsonArray(); | ||||
| 						boolean hasClient = json.has("client") && json.get("client").isJsonArray(); | ||||
| 						boolean hasServer = json.has("server") && json.get("server").isJsonArray(); | ||||
| 
 | ||||
| 						if (json.has("package") && (hasMixins || hasClient || hasServer)) { | ||||
| 							if (!onlyWithoutRefmap || !json.has("refmap") || !json.has("minVersion")) { | ||||
| 								mixinFilename.add(entry.getName()); | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} catch (Exception ignored) { | ||||
| 					// ... | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 		return mixinFilename; | ||||
| 		}).reduce(false, Boolean::logicalOr); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -29,16 +29,17 @@ import java.io.IOException; | |||
| import java.util.Collection; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import java.util.stream.Stream; | ||||
| import java.util.Objects; | ||||
| import java.util.function.Function; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.Task; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.api.artifacts.ConfigurationContainer; | ||||
| import org.gradle.api.plugins.JavaPluginConvention; | ||||
| import org.gradle.api.tasks.SourceSet; | ||||
| import org.gradle.api.tasks.TaskCollection; | ||||
| 
 | ||||
| import net.fabricmc.loom.extension.MixinApExtension; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| 
 | ||||
|  | @ -48,37 +49,46 @@ import net.fabricmc.loom.util.Constants; | |||
|  * See Java and Kapt implementations for a more deep understanding of the things passed by the children. | ||||
|  */ | ||||
| public abstract class AnnotationProcessorInvoker<T extends Task> { | ||||
| 	public static final String JAVA = "java"; | ||||
| 	public static final String SCALA = "scala"; | ||||
| 
 | ||||
| 	protected final Project project; | ||||
| 	private final Collection<Configuration> annotationProcessorConfigurations; | ||||
| 	protected final TaskCollection<T> invokerTasks; | ||||
| 	protected final Map<SourceSet, T> invokerTasks; | ||||
| 	private final Collection<Configuration> apConfigurations; | ||||
| 
 | ||||
| 	protected AnnotationProcessorInvoker(Project project, | ||||
| 										Collection<Configuration> annotationProcessorConfigurations, | ||||
| 										TaskCollection<T> invokerTasks) { | ||||
| 										Collection<Configuration> apConfigurations, | ||||
| 										Map<SourceSet, T> invokerTasks) { | ||||
| 		this.project = project; | ||||
| 		this.annotationProcessorConfigurations = annotationProcessorConfigurations; | ||||
| 		this.apConfigurations = apConfigurations; | ||||
| 		this.invokerTasks = invokerTasks; | ||||
| 	} | ||||
| 
 | ||||
| 	protected static Collection<Configuration> getApConfigurations(Project project, Function<String, String> getApConfigNameFunc) { | ||||
| 		MixinApExtension mixin = LoomGradleExtension.get(project).getMixinApExtension(); | ||||
| 		return mixin.getApConfigurationsStream(getApConfigNameFunc).collect(Collectors.toList()); | ||||
| 	} | ||||
| 
 | ||||
| 	protected abstract void passArgument(T compileTask, String key, String value); | ||||
| 
 | ||||
| 	protected abstract File getDestinationDir(T task); | ||||
| 	protected abstract File getRefmapDestinationDir(T task); | ||||
| 
 | ||||
| 	protected final String getRefmapDestination(T task, LoomGradleExtension extension) throws IOException { | ||||
| 		return new File(getDestinationDir(task), extension.getRefmapName()).getCanonicalPath(); | ||||
| 	protected final String getRefmapDestination(T task, String refmapName) throws IOException { | ||||
| 		return new File(getRefmapDestinationDir(task), refmapName).getCanonicalPath(); | ||||
| 	} | ||||
| 
 | ||||
| 	private void passMixinArguments(T task) { | ||||
| 	private void passMixinArguments(T task, SourceSet sourceSet) { | ||||
| 		try { | ||||
| 			LoomGradleExtension extension = LoomGradleExtension.get(project); | ||||
| 			LoomGradleExtension loom = LoomGradleExtension.get(project); | ||||
| 			String refmapName = Objects.requireNonNull(MixinApExtension.getMixinInformationContainer(sourceSet)).getRefmapName(); | ||||
| 			Map<String, String> args = new HashMap<>() {{ | ||||
| 					put(Constants.MixinArguments.IN_MAP_FILE_NAMED_INTERMEDIARY, extension.getMappingsProvider().tinyMappings.getCanonicalPath()); | ||||
| 					put(Constants.MixinArguments.OUT_MAP_FILE_NAMED_INTERMEDIARY, extension.getNextMixinMappings().getCanonicalPath()); | ||||
| 					put(Constants.MixinArguments.OUT_REFMAP_FILE, getRefmapDestination(task, extension)); | ||||
| 					put(Constants.MixinArguments.IN_MAP_FILE_NAMED_INTERMEDIARY, loom.getMappingsProvider().tinyMappings.getCanonicalPath()); | ||||
| 					put(Constants.MixinArguments.OUT_MAP_FILE_NAMED_INTERMEDIARY, loom.getNextMixinMappings().getCanonicalPath()); | ||||
| 					put(Constants.MixinArguments.OUT_REFMAP_FILE, getRefmapDestination(task, refmapName)); | ||||
| 					put(Constants.MixinArguments.DEFAULT_OBFUSCATION_ENV, "named:intermediary"); | ||||
| 				}}; | ||||
| 
 | ||||
| 			project.getLogger().debug("Outputting refmap to dir: " + getDestinationDir(task) + " for compile task: " + task); | ||||
| 			project.getLogger().debug("Outputting refmap to dir: " + getRefmapDestinationDir(task) + " for compile task: " + task); | ||||
| 			args.forEach((k, v) -> passArgument(task, k, v)); | ||||
| 		} catch (IOException e) { | ||||
| 			project.getLogger().error("Could not configure mixin annotation processors", e); | ||||
|  | @ -90,7 +100,7 @@ public abstract class AnnotationProcessorInvoker<T extends Task> { | |||
| 		LoomGradleExtension extension = LoomGradleExtension.get(project); | ||||
| 
 | ||||
| 		if (!extension.ideSync()) { | ||||
| 			for (Configuration processorConfig : annotationProcessorConfigurations) { | ||||
| 			for (Configuration processorConfig : apConfigurations) { | ||||
| 				project.getLogger().info("Adding mixin to classpath of AP config: " + processorConfig.getName()); | ||||
| 				// Pass named MC classpath to mixin AP classpath | ||||
| 				processorConfig.extendsFrom( | ||||
|  | @ -105,14 +115,8 @@ public abstract class AnnotationProcessorInvoker<T extends Task> { | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		for (T task : invokerTasks) { | ||||
| 			passMixinArguments(task); | ||||
| 		for (Map.Entry<SourceSet, T> entry : invokerTasks.entrySet()) { | ||||
| 			passMixinArguments(entry.getValue(), entry.getKey()); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	static Stream<SourceSet> getNonTestSourceSets(Project project) { | ||||
| 		return project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets() | ||||
| 						.stream() | ||||
| 						.filter(sourceSet -> !sourceSet.getName().equals("test")); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -25,17 +25,30 @@ | |||
| package net.fabricmc.loom.build.mixin; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Objects; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.api.plugins.JavaPlugin; | ||||
| import org.gradle.api.tasks.SourceSet; | ||||
| import org.gradle.api.tasks.compile.JavaCompile; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.extension.MixinApExtension; | ||||
| 
 | ||||
| public class JavaApInvoker extends AnnotationProcessorInvoker<JavaCompile> { | ||||
| 	public JavaApInvoker(Project project) { | ||||
| 		super(project, getConfigurations(project), project.getTasks().withType(JavaCompile.class)); | ||||
| 		super( | ||||
| 				project, | ||||
| 				AnnotationProcessorInvoker.getApConfigurations(project, JavaApInvoker::getAptConfigurationName), | ||||
| 				getInvokerTasks(project)); | ||||
| 	} | ||||
| 
 | ||||
| 	private static Map<SourceSet, JavaCompile> getInvokerTasks(Project project) { | ||||
| 		MixinApExtension mixin = LoomGradleExtension.get(project).getMixinApExtension(); | ||||
| 		return mixin.getInvokerTasksStream(AnnotationProcessorInvoker.JAVA) | ||||
| 				.collect(Collectors.toMap(Map.Entry::getKey, entry -> Objects.requireNonNull((JavaCompile) entry.getValue()))); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
|  | @ -44,18 +57,10 @@ public class JavaApInvoker extends AnnotationProcessorInvoker<JavaCompile> { | |||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	protected File getDestinationDir(JavaCompile task) { | ||||
| 	protected File getRefmapDestinationDir(JavaCompile task) { | ||||
| 		return task.getDestinationDir(); | ||||
| 	} | ||||
| 
 | ||||
| 	private static List<Configuration> getConfigurations(Project project) { | ||||
| 		// java plugin generates an AP configuration for every source set based off of the getAptConfigurationName method. | ||||
| 		return AnnotationProcessorInvoker.getNonTestSourceSets(project) | ||||
| 						.map(sourceSet -> project.getConfigurations() | ||||
| 										.getByName(getAptConfigurationName(sourceSet.getName())) | ||||
| 						).collect(Collectors.toList()); | ||||
| 	} | ||||
| 
 | ||||
| 	private static String getAptConfigurationName(String sourceSet) { | ||||
| 		// This is documented by the gradle 4.6 release notes https://docs.gradle.org/4.6/release-notes.html#potential-breaking-changes | ||||
| 		return sourceSet.equals("main") ? JavaPlugin.ANNOTATION_PROCESSOR_CONFIGURATION_NAME : sourceSet + "AnnotationProcessor"; | ||||
|  |  | |||
|  | @ -29,18 +29,18 @@ import java.io.IOException; | |||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.Paths; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Objects; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| import kotlin.Unit; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.api.tasks.SourceSet; | ||||
| import org.gradle.api.tasks.compile.JavaCompile; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
| import org.jetbrains.kotlin.gradle.plugin.KaptExtension; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.extension.MixinApExtension; | ||||
| 
 | ||||
| public class KaptApInvoker extends AnnotationProcessorInvoker<JavaCompile> { | ||||
| 	private final KaptExtension kaptExtension = project.getExtensions().getByType(KaptExtension.class); | ||||
|  | @ -48,7 +48,10 @@ public class KaptApInvoker extends AnnotationProcessorInvoker<JavaCompile> { | |||
| 	private final File dummyRefmapDirectory; | ||||
| 
 | ||||
| 	public KaptApInvoker(Project project) { | ||||
| 		super(project, getConfigurations(project), project.getTasks().withType(JavaCompile.class)); | ||||
| 		super( | ||||
| 				project, | ||||
| 				AnnotationProcessorInvoker.getApConfigurations(project, KaptApInvoker::getKaptConfigurationName), | ||||
| 				getInvokerTasks(project)); | ||||
| 
 | ||||
| 		try { | ||||
| 			dummyRefmapDirectory = Files.createTempDirectory("temp_refmap").toFile(); | ||||
|  | @ -62,18 +65,26 @@ public class KaptApInvoker extends AnnotationProcessorInvoker<JavaCompile> { | |||
| 		kaptExtension.setIncludeCompileClasspath(false); | ||||
| 	} | ||||
| 
 | ||||
| 	private static Map<SourceSet, JavaCompile> getInvokerTasks(Project project) { | ||||
| 		MixinApExtension mixin = LoomGradleExtension.get(project).getMixinApExtension(); | ||||
| 		return mixin.getInvokerTasksStream(AnnotationProcessorInvoker.JAVA) | ||||
| 				.collect(Collectors.toMap(Map.Entry::getKey, entry -> Objects.requireNonNull((JavaCompile) entry.getValue()))); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void configureMixin() { | ||||
| 		super.configureMixin(); | ||||
| 
 | ||||
| 		for (JavaCompile task : invokerTasks) { | ||||
| 		for (Map.Entry<SourceSet, JavaCompile> entry : invokerTasks.entrySet()) { | ||||
| 			// Kapt only allows specifying javac args to all annotation processors at once. So we need to specify some dummy | ||||
| 			// target location for the refmap and then move it to the correct place for each sourceset | ||||
| 			JavaCompile task = entry.getValue(); | ||||
| 			SourceSet sourceSet = entry.getKey(); | ||||
| 			task.doLast(t -> { | ||||
| 				try { | ||||
| 					LoomGradleExtension extension = LoomGradleExtension.get(project); | ||||
| 					Path src = Paths.get(getRefmapDestination(task, extension)); | ||||
| 					Path dest = Paths.get(task.getDestinationDir().toString(), extension.getRefmapName()); | ||||
| 					String refmapName = Objects.requireNonNull(MixinApExtension.getMixinInformationContainer(sourceSet)).getRefmapName(); | ||||
| 					Path src = Paths.get(getRefmapDestination(task, refmapName)); | ||||
| 					Path dest = Paths.get(task.getDestinationDir().toString(), refmapName); | ||||
| 
 | ||||
| 					// Possible that no mixin annotations exist | ||||
| 					if (Files.exists(src)) { | ||||
|  | @ -87,15 +98,6 @@ public class KaptApInvoker extends AnnotationProcessorInvoker<JavaCompile> { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@NotNull | ||||
| 	private static List<Configuration> getConfigurations(Project project) { | ||||
| 		// Kapt generates an AP configuration for every source set based off of the getKaptConfigurationName method. | ||||
| 		return AnnotationProcessorInvoker.getNonTestSourceSets(project) | ||||
| 						.map(sourceSet -> project.getConfigurations() | ||||
| 										.getByName(getKaptConfigurationName(sourceSet.getName())) | ||||
| 						).collect(Collectors.toList()); | ||||
| 	} | ||||
| 
 | ||||
| 	// Pulled out from the internal class: https://github.com/JetBrains/kotlin/blob/33a0ec9b4f40f3d6f1f96b2db504ade4c2fafe03/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt#L92 | ||||
| 	private static String getKaptConfigurationName(String sourceSetName) { | ||||
| 		if (!sourceSetName.equals(SourceSet.MAIN_SOURCE_SET_NAME)) { | ||||
|  | @ -116,7 +118,7 @@ public class KaptApInvoker extends AnnotationProcessorInvoker<JavaCompile> { | |||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	protected File getDestinationDir(JavaCompile task) { | ||||
| 	protected File getRefmapDestinationDir(JavaCompile task) { | ||||
| 		return dummyRefmapDirectory; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -25,17 +25,31 @@ | |||
| package net.fabricmc.loom.build.mixin; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.util.Map; | ||||
| import java.util.Objects; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| import com.google.common.collect.ImmutableList; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.tasks.SourceSet; | ||||
| import org.gradle.api.tasks.scala.ScalaCompile; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.extension.MixinApExtension; | ||||
| 
 | ||||
| public class ScalaApInvoker extends AnnotationProcessorInvoker<ScalaCompile> { | ||||
| 	public ScalaApInvoker(Project project) { | ||||
| 		super(project, | ||||
| 		super( | ||||
| 				project, | ||||
| 				// Scala just uses the java AP configuration afaik. This of course assumes the java AP also gets configured. | ||||
| 				ImmutableList.of(), | ||||
| 						project.getTasks().withType(ScalaCompile.class)); | ||||
| 				getInvokerTasks(project)); | ||||
| 	} | ||||
| 
 | ||||
| 	private static Map<SourceSet, ScalaCompile> getInvokerTasks(Project project) { | ||||
| 		MixinApExtension mixin = LoomGradleExtension.get(project).getMixinApExtension(); | ||||
| 		return mixin.getInvokerTasksStream(AnnotationProcessorInvoker.SCALA) | ||||
| 				.collect(Collectors.toMap(Map.Entry::getKey, entry -> Objects.requireNonNull((ScalaCompile) entry.getValue()))); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
|  | @ -44,7 +58,7 @@ public class ScalaApInvoker extends AnnotationProcessorInvoker<ScalaCompile> { | |||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	protected File getDestinationDir(ScalaCompile task) { | ||||
| 	protected File getRefmapDestinationDir(ScalaCompile task) { | ||||
| 		return task.getDestinationDir(); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -33,6 +33,7 @@ import org.gradle.api.tasks.compile.JavaCompile; | |||
| import org.gradle.api.tasks.javadoc.Javadoc; | ||||
| import org.gradle.jvm.tasks.Jar; | ||||
| 
 | ||||
| import net.fabricmc.loom.extension.MixinApExtension; | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.build.mixin.JavaApInvoker; | ||||
| import net.fabricmc.loom.build.mixin.KaptApInvoker; | ||||
|  | @ -143,6 +144,9 @@ public final class CompileConfiguration { | |||
| 			System.setProperty("log4j.skipJansi", "true"); | ||||
| 
 | ||||
| 			project.getLogger().info("Configuring compiler arguments for Java"); | ||||
| 			MixinApExtension mixinApExtension = LoomGradleExtension.get(project).getMixinApExtension(); | ||||
| 			mixinApExtension.init(); | ||||
| 
 | ||||
| 			new JavaApInvoker(project).configureMixin(); | ||||
| 
 | ||||
| 			if (project.getPluginManager().hasPlugin("scala")) { | ||||
|  |  | |||
|  | @ -36,6 +36,7 @@ import org.gradle.api.artifacts.Dependency; | |||
| import org.gradle.api.file.ConfigurableFileCollection; | ||||
| import org.gradle.api.plugins.BasePluginConvention; | ||||
| 
 | ||||
| import net.fabricmc.loom.api.MixinApExtensionAPI; | ||||
| import net.fabricmc.loom.api.decompilers.LoomDecompiler; | ||||
| import net.fabricmc.loom.api.LoomGradleExtensionAPI; | ||||
| import net.fabricmc.loom.configuration.ide.RunConfigSettings; | ||||
|  | @ -159,6 +160,11 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA | |||
| 		return remapMod; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void mixin(Action<MixinApExtensionAPI> action) { | ||||
| 		action.execute(getMixinApExtension()); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void setCustomManifest(String customManifest) { | ||||
| 		Objects.requireNonNull(customManifest, "Custom manifest cannot be null"); | ||||
|  | @ -174,6 +180,8 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA | |||
| 
 | ||||
| 	protected abstract LoomFiles getFiles(); | ||||
| 
 | ||||
| 	protected abstract MixinApExtension getMixinApExtension(); | ||||
| 
 | ||||
| 	// This is here to ensure that LoomGradleExtensionApiImpl compiles without any unimplemented methods | ||||
| 	private final class EnsureCompile extends LoomGradleExtensionApiImpl { | ||||
| 		private EnsureCompile() { | ||||
|  | @ -190,5 +198,10 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA | |||
| 		protected LoomFiles getFiles() { | ||||
| 			throw new RuntimeException("Yeah... something is really wrong"); | ||||
| 		} | ||||
| 
 | ||||
| 		@Override | ||||
| 		protected MixinApExtension getMixinApExtension() { | ||||
| 			throw new RuntimeException("Yeah... something is really wrong"); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -47,6 +47,7 @@ import net.fabricmc.loom.configuration.processors.JarProcessorManager; | |||
| 
 | ||||
| public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implements LoomGradleExtension { | ||||
| 	private final Project project; | ||||
| 	private final MixinApExtension mixinApExtension; | ||||
| 	private final LoomFiles loomFiles; | ||||
| 	private final ConfigurableFileCollection unmappedMods; | ||||
| 
 | ||||
|  | @ -62,6 +63,7 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen | |||
| 	public LoomGradleExtensionImpl(Project project, LoomFiles files) { | ||||
| 		super(project, files); | ||||
| 		this.project = project; | ||||
| 		this.mixinApExtension = new MixinApExtensionImpl(project); | ||||
| 		this.loomFiles = files; | ||||
| 		this.unmappedMods = project.files(); | ||||
| 	} | ||||
|  | @ -160,4 +162,9 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen | |||
| 
 | ||||
| 		return provider; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public MixinApExtension getMixinApExtension() { | ||||
| 		return this.mixinApExtension; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
							
								
								
									
										126
									
								
								src/main/java/net/fabricmc/loom/extension/MixinApExtension.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								src/main/java/net/fabricmc/loom/extension/MixinApExtension.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,126 @@ | |||
| /* | ||||
|  * This file is part of fabric-loom, licensed under the MIT License (MIT). | ||||
|  * | ||||
|  * Copyright (c) 2016-2017 FabricMC | ||||
|  * | ||||
|  * 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 net.fabricmc.loom.extension; | ||||
| 
 | ||||
| import java.util.Collection; | ||||
| import java.util.Map; | ||||
| import java.util.Objects; | ||||
| import java.util.function.Function; | ||||
| import java.util.stream.Stream; | ||||
| 
 | ||||
| import org.gradle.api.InvalidUserDataException; | ||||
| import org.gradle.api.Task; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.api.plugins.ExtraPropertiesExtension; | ||||
| import org.gradle.api.tasks.Input; | ||||
| import org.gradle.api.tasks.SourceSet; | ||||
| import org.gradle.api.tasks.util.PatternSet; | ||||
| import org.jetbrains.annotations.ApiStatus; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
| import org.jetbrains.annotations.Nullable; | ||||
| 
 | ||||
| import net.fabricmc.loom.api.MixinApExtensionAPI; | ||||
| 
 | ||||
| /** | ||||
|  * A gradle extension to configure mixin annotation processor. | ||||
|  */ | ||||
| @ApiStatus.Experimental | ||||
| public interface MixinApExtension extends MixinApExtensionAPI { | ||||
| 	String MIXIN_INFORMATION_CONTAINER = "mixin"; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * An information container stores necessary information | ||||
| 	 * for configuring the mixin annotation processor. It's stored | ||||
| 	 * in [SourceSet].ext.mixin. | ||||
| 	 */ | ||||
| 	final class MixinInformationContainer { | ||||
| 		private final SourceSet sourceSet; | ||||
| 		private final String refmapName; | ||||
| 		private Stream<String> mixinJsonNames; | ||||
| 
 | ||||
| 		final PatternSet mixinJsonPattern; | ||||
| 
 | ||||
| 		public MixinInformationContainer(@NotNull SourceSet sourceSet, | ||||
| 										@NotNull String refmapName, | ||||
| 										@NotNull PatternSet mixinJsonPattern) { | ||||
| 			this.sourceSet = sourceSet; | ||||
| 			this.refmapName = refmapName; | ||||
| 			this.mixinJsonPattern = mixinJsonPattern; | ||||
| 		} | ||||
| 
 | ||||
| 		void setMixinJsonNames(@NotNull Stream<String> mixinJsonNames) { | ||||
| 			if (this.mixinJsonNames == null) { | ||||
| 				this.mixinJsonNames = mixinJsonNames; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		@NotNull | ||||
| 		public Stream<String> getMixinJsonNames() { | ||||
| 			return Objects.requireNonNull(mixinJsonNames); | ||||
| 		} | ||||
| 
 | ||||
| 		@NotNull | ||||
| 		public SourceSet getSourceSet() { | ||||
| 			return sourceSet; | ||||
| 		} | ||||
| 
 | ||||
| 		@NotNull | ||||
| 		public String getRefmapName() { | ||||
| 			return refmapName; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@Nullable | ||||
| 	static MixinInformationContainer getMixinInformationContainer(SourceSet sourceSet) { | ||||
| 		ExtraPropertiesExtension extra = sourceSet.getExtensions().getExtraProperties(); | ||||
| 		return extra.has(MIXIN_INFORMATION_CONTAINER) ? (MixinInformationContainer) extra.get(MIXIN_INFORMATION_CONTAINER) : null; | ||||
| 	} | ||||
| 
 | ||||
| 	static void setMixinInformationContainer(SourceSet sourceSet, MixinInformationContainer container) { | ||||
| 		ExtraPropertiesExtension extra = sourceSet.getExtensions().getExtraProperties(); | ||||
| 
 | ||||
| 		if (extra.has(MIXIN_INFORMATION_CONTAINER)) { | ||||
| 			throw new InvalidUserDataException("The sourceSet " + sourceSet.getName() | ||||
| 					+ " has been configured for mixin annotation processor multiple times"); | ||||
| 		} | ||||
| 
 | ||||
| 		extra.set(MIXIN_INFORMATION_CONTAINER, container); | ||||
| 	} | ||||
| 
 | ||||
| 	@NotNull | ||||
| 	Stream<SourceSet> getMixinSourceSetsStream(); | ||||
| 
 | ||||
| 	@NotNull | ||||
| 	Stream<Configuration> getApConfigurationsStream(Function<String, String> getApConfigNameFunc); | ||||
| 
 | ||||
| 	@NotNull | ||||
| 	Stream<Map.Entry<SourceSet, Task>> getInvokerTasksStream(String compileTaskLanguage); | ||||
| 
 | ||||
| 	@NotNull | ||||
| 	@Input | ||||
| 	Collection<SourceSet> getMixinSourceSets(); | ||||
| 
 | ||||
| 	void init(); | ||||
| } | ||||
|  | @ -0,0 +1,110 @@ | |||
| /* | ||||
|  * This file is part of fabric-loom, licensed under the MIT License (MIT). | ||||
|  * | ||||
|  * Copyright (c) 2021 FabricMC | ||||
|  * | ||||
|  * 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 net.fabricmc.loom.extension; | ||||
| 
 | ||||
| import org.gradle.api.Action; | ||||
| import org.gradle.api.InvalidUserDataException; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.plugins.JavaPluginConvention; | ||||
| import org.gradle.api.tasks.SourceSet; | ||||
| import org.gradle.api.tasks.util.PatternSet; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.api.MixinApExtensionAPI; | ||||
| 
 | ||||
| public abstract class MixinApExtensionApiImpl implements MixinApExtensionAPI { | ||||
| 	protected abstract Project getProject(); | ||||
| 	protected abstract PatternSet add0(SourceSet sourceSet, String refmapName); | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void add(SourceSet sourceSet, String refmapName, Action<PatternSet> action) { | ||||
| 		PatternSet pattern = add0(sourceSet, refmapName); | ||||
| 		action.execute(pattern); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void add(SourceSet sourceSet, String refmapName) { | ||||
| 		add(sourceSet, refmapName, x -> { }); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void add(String sourceSetName, String refmapName, Action<PatternSet> action) { | ||||
| 		// try to find sourceSet with name sourceSetName in this project | ||||
| 		SourceSet sourceSet = getProject().getConvention().getPlugin(JavaPluginConvention.class) | ||||
| 				.getSourceSets().findByName(sourceSetName); | ||||
| 
 | ||||
| 		if (sourceSet == null) { | ||||
| 			throw new InvalidUserDataException("No sourceSet " + sourceSetName + " was found"); | ||||
| 		} | ||||
| 
 | ||||
| 		PatternSet pattern = add0(sourceSet, refmapName); | ||||
| 		action.execute(pattern); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void add(String sourceSetName, String refmapName) { | ||||
| 		add(sourceSetName, refmapName, x -> { }); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void add(SourceSet sourceSet, Action<PatternSet> action) { | ||||
| 		LoomGradleExtension extension = LoomGradleExtension.get(getProject()); | ||||
| 		add(sourceSet, extension.getRefmapName(), action); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void add(SourceSet sourceSet) { | ||||
| 		add(sourceSet, x -> { }); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void add(String sourceSetName, Action<PatternSet> action) { | ||||
| 		LoomGradleExtension extension = LoomGradleExtension.get(getProject()); | ||||
| 		add(sourceSetName, extension.getRefmapName(), action); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void add(String sourceSetName) { | ||||
| 		add(sourceSetName, x -> { }); | ||||
| 	} | ||||
| 
 | ||||
| 	// This is here to ensure that LoomGradleExtensionApiImpl compiles without any unimplemented methods | ||||
| 	private final class EnsureCompile extends MixinApExtensionApiImpl { | ||||
| 		private EnsureCompile() { | ||||
| 			super(); | ||||
| 			throw new RuntimeException(); | ||||
| 		} | ||||
| 
 | ||||
| 		@Override | ||||
| 		protected Project getProject() { | ||||
| 			throw new RuntimeException("Yeah... something is really wrong"); | ||||
| 		} | ||||
| 
 | ||||
| 		@Override | ||||
| 		protected PatternSet add0(SourceSet sourceSet, String refmapName) { | ||||
| 			throw new RuntimeException("Yeah... something is really wrong"); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,125 @@ | |||
| /* | ||||
|  * This file is part of fabric-loom, licensed under the MIT License (MIT). | ||||
|  * | ||||
|  * Copyright (c) 2021 FabricMC | ||||
|  * | ||||
|  * 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 net.fabricmc.loom.extension; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.util.AbstractMap; | ||||
| import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.Map; | ||||
| import java.util.function.Function; | ||||
| import java.util.stream.Collectors; | ||||
| import java.util.stream.Stream; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.Task; | ||||
| import org.gradle.api.UnknownTaskException; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.api.plugins.JavaPluginConvention; | ||||
| import org.gradle.api.tasks.Input; | ||||
| import org.gradle.api.tasks.SourceSet; | ||||
| import org.gradle.api.tasks.util.PatternSet; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
| 
 | ||||
| public class MixinApExtensionImpl extends MixinApExtensionApiImpl implements MixinApExtension { | ||||
| 	private boolean isDefault; | ||||
| 	private final Project project; | ||||
| 
 | ||||
| 	public MixinApExtensionImpl(Project project) { | ||||
| 		this.isDefault = true; | ||||
| 		this.project = project; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public Project getProject() { | ||||
| 		return this.project; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	protected PatternSet add0(SourceSet sourceSet, String refmapName) { | ||||
| 		PatternSet pattern = new PatternSet().setIncludes(Collections.singletonList("*.mixins.json")); | ||||
| 		MixinApExtension.setMixinInformationContainer(sourceSet, new MixinApExtension.MixinInformationContainer(sourceSet, refmapName, pattern)); | ||||
| 
 | ||||
| 		isDefault = false; | ||||
| 
 | ||||
| 		return pattern; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	@NotNull | ||||
| 	public Stream<SourceSet> getMixinSourceSetsStream() { | ||||
| 		return project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().stream() | ||||
| 				.filter(sourceSet -> { | ||||
| 					MixinApExtension.MixinInformationContainer container = MixinApExtension.getMixinInformationContainer(sourceSet); | ||||
| 
 | ||||
| 					if (container != null) { | ||||
| 						PatternSet pattern = container.mixinJsonPattern; | ||||
| 						Stream<String> mixinJsonNames = sourceSet.getResources() | ||||
| 								.matching(pattern).getFiles().stream().map(File::getName); | ||||
| 						container.setMixinJsonNames(mixinJsonNames); | ||||
| 						return true; | ||||
| 					} | ||||
| 
 | ||||
| 					return false; | ||||
| 				}); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	@NotNull | ||||
| 	public Stream<Configuration> getApConfigurationsStream(Function<String, String> getApConfigNameFunc) { | ||||
| 		return getMixinSourceSetsStream() | ||||
| 				.map(sourceSet -> project.getConfigurations().getByName(getApConfigNameFunc.apply(sourceSet.getName()))); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	@NotNull | ||||
| 	public Stream<Map.Entry<SourceSet, Task>> getInvokerTasksStream(String compileTaskLanguage) { | ||||
| 		return getMixinSourceSetsStream() | ||||
| 				.flatMap(sourceSet -> { | ||||
| 					try { | ||||
| 						Task task = project.getTasks().getByName(sourceSet.getCompileTaskName(compileTaskLanguage)); | ||||
| 						return Stream.of(new AbstractMap.SimpleEntry<>(sourceSet, task)); | ||||
| 					} catch (UnknownTaskException ignored) { | ||||
| 						return Stream.empty(); | ||||
| 					} | ||||
| 				}); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	@NotNull | ||||
| 	@Input | ||||
| 	public Collection<SourceSet> getMixinSourceSets() { | ||||
| 		return getMixinSourceSetsStream().collect(Collectors.toList()); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void init() { | ||||
| 		if (isDefault) { | ||||
| 			project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().forEach(this::add); | ||||
| 		} | ||||
| 
 | ||||
| 		isDefault = false; | ||||
| 	} | ||||
| } | ||||
|  | @ -170,7 +170,7 @@ public class RemapJarTask extends Jar { | |||
| 						throw new RuntimeException("Failed to remap " + input + " to " + output + " - file missing!"); | ||||
| 					} | ||||
| 
 | ||||
| 					if (MixinRefmapHelper.addRefmapName(extension.getRefmapName(), output)) { | ||||
| 					if (MixinRefmapHelper.addRefmapName(project, output)) { | ||||
| 						project.getLogger().debug("Transformed mixin reference maps in output JAR!"); | ||||
| 					} | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,73 @@ | |||
| /* | ||||
|  * This file is part of fabric-loom, licensed under the MIT License (MIT). | ||||
|  * | ||||
|  * Copyright (c) 2016-2017 FabricMC | ||||
|  * | ||||
|  * 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 net.fabricmc.loom.test.integration | ||||
| 
 | ||||
| import net.fabricmc.loom.test.util.ProjectTestTrait | ||||
| import spock.lang.Specification | ||||
| import spock.lang.Unroll | ||||
| import com.google.gson.JsonParser; | ||||
| import java.util.jar.JarFile | ||||
| 
 | ||||
| import static org.gradle.testkit.runner.TaskOutcome.SUCCESS | ||||
| 
 | ||||
| class MixinApAutoRefmapTest extends Specification implements ProjectTestTrait { | ||||
|     @Override | ||||
|     String name() { | ||||
|         "mixinApAutoRefmap" | ||||
|     } | ||||
| 
 | ||||
|     @Unroll | ||||
|     def "build (gradle #gradle)"() { | ||||
|         when: | ||||
|         def result = create("build", gradle) | ||||
| 
 | ||||
|         then: | ||||
|         result.task(":build").outcome == SUCCESS | ||||
| 
 | ||||
|         // verify the ref-map name is correctly generated | ||||
|         def jar = new JarFile(getOutputFile("fabric-example-mod-1.0.0-universal.jar").absoluteFile) | ||||
|         jar.getEntry("refmap0000.json") == null | ||||
|         jar.getEntry("refmap0001.json") != null | ||||
|         jar.getEntry("refmap0002.json") != null | ||||
|         jar.getEntry("refmap0003.json") != null | ||||
| 
 | ||||
|         def j1 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("main.mixins.json")))) | ||||
|         j1.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0001.json" | ||||
| 
 | ||||
|         def j2 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("m0.mixins.json")))) | ||||
|         j2.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0002.json" | ||||
| 
 | ||||
|         def j3 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("m1_1.mixins.json")))) | ||||
|         j3.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0003.json" | ||||
| 
 | ||||
|         def j4 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("m1_2.mixins.json")))) | ||||
|         !j4.asJsonObject.has("refmap") | ||||
| 
 | ||||
|         where: | ||||
|         gradle              | _ | ||||
|         DEFAULT_GRADLE      | _ | ||||
|         PRE_RELEASE_GRADLE  | _ | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,63 @@ | |||
| /* | ||||
|  * This file is part of fabric-loom, licensed under the MIT License (MIT). | ||||
|  * | ||||
|  * Copyright (c) 2016-2017 FabricMC | ||||
|  * | ||||
|  * 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 net.fabricmc.loom.test.integration | ||||
| 
 | ||||
| import net.fabricmc.loom.test.util.ProjectTestTrait | ||||
| import spock.lang.Specification | ||||
| import spock.lang.Unroll | ||||
| 
 | ||||
| import java.util.jar.JarFile | ||||
| 
 | ||||
| import static org.gradle.testkit.runner.TaskOutcome.SUCCESS | ||||
| 
 | ||||
| class MixinApSimpleTest extends Specification implements ProjectTestTrait { | ||||
|     @Override | ||||
|     String name() { | ||||
|         "mixinApSimple" | ||||
|     } | ||||
| 
 | ||||
|     @Unroll | ||||
|     def "build (gradle #gradle)"() { | ||||
|         when: | ||||
|         def result = create("build", gradle) | ||||
| 
 | ||||
|         then: | ||||
|         result.task(":build").outcome == SUCCESS | ||||
| 
 | ||||
|         // verify the ref-map name is correctly generated | ||||
|         def main = new JarFile(getOutputFile("fabric-example-mod-1.0.0-dev.jar").absoluteFile) | ||||
|         main.getEntry("main-refmap0000.json") != null | ||||
|         def mixin = new JarFile(getOutputFile("fabric-example-mod-1.0.0-mixin.jar").absoluteFile) | ||||
|         mixin.getEntry("default-refmap0000.json") != null | ||||
|         def mixin1 = new JarFile(getOutputFile("fabric-example-mod-1.0.0-mixin1.jar").absoluteFile) | ||||
|         mixin1.getEntry("main-refmap0000.json") == null | ||||
|         mixin1.getEntry("default-refmap0000.json") == null | ||||
| 
 | ||||
|         where: | ||||
|         gradle              | _ | ||||
|         DEFAULT_GRADLE      | _ | ||||
|         PRE_RELEASE_GRADLE  | _ | ||||
|     } | ||||
| } | ||||
							
								
								
									
										139
									
								
								src/test/resources/projects/mixinApAutoRefmap/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								src/test/resources/projects/mixinApAutoRefmap/build.gradle
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,139 @@ | |||
| plugins { | ||||
| 	id 'fabric-loom' | ||||
| 	id 'com.github.johnrengelman.shadow' version '7.0.0' | ||||
| 	id 'maven-publish' | ||||
| } | ||||
| 
 | ||||
| sourceCompatibility = JavaVersion.VERSION_16 | ||||
| targetCompatibility = JavaVersion.VERSION_16 | ||||
| 
 | ||||
| archivesBaseName = project.archives_base_name | ||||
| version = project.mod_version | ||||
| group = project.maven_group | ||||
| 
 | ||||
| repositories { | ||||
| 	// Add repositories to retrieve artifacts from in here. | ||||
| 	// You should only use this when depending on other mods because | ||||
| 	// Loom adds the essential maven repositories to download Minecraft and libraries from automatically. | ||||
| 	// See https://docs.gradle.org/current/userguide/declaring_repositories.html | ||||
| 	// for more information about repositories. | ||||
| } | ||||
| 
 | ||||
| dependencies { | ||||
| 	// To change the versions see the gradle.properties file | ||||
| 	minecraft "com.mojang:minecraft:${project.minecraft_version}" | ||||
| 	mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" | ||||
| 	modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" | ||||
| 
 | ||||
| 	// Fabric API. This is technically optional, but you probably want it anyway. | ||||
| 	modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" | ||||
| 
 | ||||
| 	// PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. | ||||
| 	// You may need to force-disable transitiveness on them. | ||||
| } | ||||
| 
 | ||||
| sourceSets.register("mixin") { | ||||
| 	it.compileClasspath += sourceSets["main"].compileClasspath | ||||
| 	it.runtimeClasspath += sourceSets["main"].runtimeClasspath | ||||
| } | ||||
| sourceSets.register("mixin1") { | ||||
| 	it.compileClasspath += sourceSets["main"].compileClasspath | ||||
| 	it.runtimeClasspath += sourceSets["main"].runtimeClasspath | ||||
| } | ||||
| 
 | ||||
| processResources { | ||||
| 	inputs.property "version", project.version | ||||
| 
 | ||||
| 	filesMatching("fabric.mod.json") { | ||||
| 		expand "version": project.version | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| tasks.withType(JavaCompile).configureEach { | ||||
| 	// ensure that the encoding is set to UTF-8, no matter what the system default is | ||||
| 	// this fixes some edge cases with special characters not displaying correctly | ||||
| 	// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html | ||||
| 	// If Javadoc is generated, this must be specified in that task too. | ||||
| 	it.options.encoding = "UTF-8" | ||||
| 
 | ||||
| 	// Minecraft 1.17 (21w19a) upwards uses Java 16. | ||||
| 	it.options.release = 16 | ||||
| } | ||||
| 
 | ||||
| java { | ||||
| 	// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task | ||||
| 	// if it is present. | ||||
| 	// If you remove this line, sources will not be generated. | ||||
| 	withSourcesJar() | ||||
| } | ||||
| 
 | ||||
| loom { | ||||
| 	refmapName = "refmap0000.json" | ||||
| 
 | ||||
| 	mixin { | ||||
| 		add(sourceSets["main"], "refmap0001.json") | ||||
| 		add(sourceSets["mixin"], "refmap0002.json") | ||||
| 		add(sourceSets["mixin1"], "refmap0003.json") { | ||||
| 			it.exclude("m1_2.mixins.json") | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| shadowJar { | ||||
| 	archiveClassifier.set("universal-dev") | ||||
| 	configurations = [] | ||||
| 
 | ||||
| 	from(sourceSets["main"].output) | ||||
| 	from(sourceSets["mixin"].output) | ||||
| 	from(sourceSets["mixin1"].output) | ||||
| } | ||||
| 
 | ||||
| remapJar { | ||||
| 	dependsOn(shadowJar) | ||||
| 	archiveClassifier.set("universal") | ||||
| 	input.fileValue(tasks["shadowJar"].outputs.files.singleFile) | ||||
| } | ||||
| 
 | ||||
| jar { | ||||
| 	from("LICENSE") { | ||||
| 		rename { "${it}_${project.archivesBaseName}"} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| tasks.register("mixinJar0", Jar.class) { | ||||
| 	it.archiveClassifier.set("mixin") | ||||
| 	it.from(sourceSets["mixin"].output) | ||||
| } | ||||
| 
 | ||||
| tasks.register("mixinJar1", Jar.class) { | ||||
| 	it.archiveClassifier.set("mixin1") | ||||
| 	it.from(sourceSets["mixin1"].output) | ||||
| } | ||||
| 
 | ||||
| assemble { | ||||
| 	dependsOn tasks["mixinJar0"] | ||||
| 	dependsOn tasks["mixinJar1"] | ||||
| } | ||||
| 
 | ||||
| // configure the maven publication | ||||
| publishing { | ||||
| 	publications { | ||||
| 		mavenJava(MavenPublication) { | ||||
| 			// add all the jars that should be included when publishing to maven | ||||
| 			artifact(remapJar) { | ||||
| 				builtBy remapJar | ||||
| 			} | ||||
| 			artifact(sourcesJar) { | ||||
| 				builtBy remapSourcesJar | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. | ||||
| 	repositories { | ||||
| 		// Add repositories to publish to here. | ||||
| 		// Notice: This block does NOT have the same function as the block in the top level. | ||||
| 		// The repositories here will be used for publishing your artifact, not for | ||||
| 		// retrieving dependencies. | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,16 @@ | |||
| # Done to increase the memory available to gradle. | ||||
| org.gradle.jvmargs=-Xmx1G | ||||
| 
 | ||||
| # Fabric Properties | ||||
| 	# check these on https://fabricmc.net/versions.html | ||||
| 	minecraft_version=1.17 | ||||
| 	yarn_mappings=1.17+build.13 | ||||
| 	loader_version=0.11.6 | ||||
| 
 | ||||
| # Mod Properties | ||||
| 	mod_version = 1.0.0 | ||||
| 	maven_group = com.example | ||||
| 	archives_base_name = fabric-example-mod | ||||
| 
 | ||||
| # Dependencies | ||||
| 	fabric_version=0.36.0+1.17 | ||||
|  | @ -0,0 +1,10 @@ | |||
| pluginManagement { | ||||
|     repositories { | ||||
|         maven { | ||||
|             name = 'Fabric' | ||||
|             url = 'https://maven.fabricmc.net/' | ||||
|         } | ||||
|         gradlePluginPortal() | ||||
|         mavenLocal() | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| package net.fabricmc.example; | ||||
| 
 | ||||
| import net.fabricmc.api.ModInitializer; | ||||
| 
 | ||||
| public class ExampleMod implements ModInitializer { | ||||
| 	@Override | ||||
| 	public void onInitialize() { | ||||
| 		// This code runs as soon as Minecraft is in a mod-load-ready state. | ||||
| 		// However, some things (like resources) may still be uninitialized. | ||||
| 		// Proceed with mild caution. | ||||
| 
 | ||||
| 		System.out.println("Hello Fabric world!"); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,15 @@ | |||
| package net.fabricmc.example.mixin; | ||||
| 
 | ||||
| import net.minecraft.client.gui.screen.ChatScreen; | ||||
| import org.spongepowered.asm.mixin.Mixin; | ||||
| import org.spongepowered.asm.mixin.injection.At; | ||||
| import org.spongepowered.asm.mixin.injection.Inject; | ||||
| import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; | ||||
| 
 | ||||
| @Mixin(ChatScreen.class) | ||||
| public class ExampleMixinMain { | ||||
| 	@Inject(at = @At("HEAD"), method = "init()V") | ||||
| 	private void init(CallbackInfo info) { | ||||
| 		System.out.println("This line is printed by an example mod mixin!"); | ||||
| 	} | ||||
| } | ||||
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 453 B | 
|  | @ -0,0 +1,37 @@ | |||
| { | ||||
|   "schemaVersion": 1, | ||||
|   "id": "modid", | ||||
|   "version": "${version}", | ||||
| 
 | ||||
|   "name": "Example Mod", | ||||
|   "description": "This is an example description! Tell everyone what your mod is about!", | ||||
|   "authors": [ | ||||
|     "Me!" | ||||
|   ], | ||||
|   "contact": { | ||||
|     "homepage": "https://fabricmc.net/", | ||||
|     "sources": "https://github.com/FabricMC/fabric-example-mod" | ||||
|   }, | ||||
| 
 | ||||
|   "license": "CC0-1.0", | ||||
|   "icon": "assets/modid/icon.png", | ||||
| 
 | ||||
|   "environment": "*", | ||||
|   "entrypoints": { | ||||
|     "main": [ | ||||
|       "net.fabricmc.example.ExampleMod" | ||||
|     ] | ||||
|   }, | ||||
|   "mixins": [ | ||||
|   ], | ||||
| 
 | ||||
|   "depends": { | ||||
|     "fabricloader": ">=0.11.3", | ||||
|     "fabric": "*", | ||||
|     "minecraft": "1.17.x", | ||||
|     "java": ">=16" | ||||
|   }, | ||||
|   "suggests": { | ||||
|     "another-mod": "*" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "required": true, | ||||
|   "minVersion": "0.8", | ||||
|   "package": "net.fabricmc.example.mixin", | ||||
|   "compatibilityLevel": "JAVA_16", | ||||
|   "mixins": [ | ||||
|   ], | ||||
|   "client": [ | ||||
|       "ExampleMixinMain" | ||||
|   ], | ||||
|   "injectors": { | ||||
|     "defaultRequire": 1 | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,15 @@ | |||
| package net.fabricmc.example.mixin; | ||||
| 
 | ||||
| import net.minecraft.client.gui.screen.TitleScreen; | ||||
| import org.spongepowered.asm.mixin.Mixin; | ||||
| import org.spongepowered.asm.mixin.injection.At; | ||||
| import org.spongepowered.asm.mixin.injection.Inject; | ||||
| import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; | ||||
| 
 | ||||
| @Mixin(TitleScreen.class) | ||||
| public class ExampleMixin0 { | ||||
| 	@Inject(at = @At("HEAD"), method = "init()V") | ||||
| 	private void init(CallbackInfo info) { | ||||
| 		System.out.println("This line is printed by an example mod mixin!"); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "required": true, | ||||
|   "minVersion": "0.8", | ||||
|   "package": "net.fabricmc.example.mixin", | ||||
|   "compatibilityLevel": "JAVA_16", | ||||
|   "mixins": [ | ||||
|   ], | ||||
|   "client": [ | ||||
|       "ExampleMixin0" | ||||
|   ], | ||||
|   "injectors": { | ||||
|     "defaultRequire": 1 | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,15 @@ | |||
| package net.fabricmc.example.mixin; | ||||
| 
 | ||||
| import net.minecraft.client.gui.screen.TitleScreen; | ||||
| import org.spongepowered.asm.mixin.Mixin; | ||||
| import org.spongepowered.asm.mixin.injection.At; | ||||
| import org.spongepowered.asm.mixin.injection.Inject; | ||||
| import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; | ||||
| 
 | ||||
| @Mixin(TitleScreen.class) | ||||
| public class ExampleMixin1_1 { | ||||
| 	@Inject(at = @At("HEAD"), method = "init()V") | ||||
| 	private void init(CallbackInfo info) { | ||||
| 		System.out.println("This line is printed by an example mod mixin!"); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,15 @@ | |||
| package net.fabricmc.example.mixin; | ||||
| 
 | ||||
| import net.minecraft.client.gui.screen.TitleScreen; | ||||
| import org.spongepowered.asm.mixin.Mixin; | ||||
| import org.spongepowered.asm.mixin.injection.At; | ||||
| import org.spongepowered.asm.mixin.injection.Inject; | ||||
| import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; | ||||
| 
 | ||||
| @Mixin(TitleScreen.class) | ||||
| public class ExampleMixin1_2 { | ||||
| 	@Inject(at = @At("HEAD"), method = "init()V") | ||||
| 	private void init(CallbackInfo info) { | ||||
| 		System.out.println("This line is printed by an example mod mixin!"); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "required": true, | ||||
|   "minVersion": "0.8", | ||||
|   "package": "net.fabricmc.example.mixin", | ||||
|   "compatibilityLevel": "JAVA_16", | ||||
|   "mixins": [ | ||||
|   ], | ||||
|   "client": [ | ||||
|       "ExampleMixin1_1" | ||||
|   ], | ||||
|   "injectors": { | ||||
|     "defaultRequire": 1 | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "required": true, | ||||
|   "minVersion": "0.8", | ||||
|   "package": "net.fabricmc.example.mixin", | ||||
|   "compatibilityLevel": "JAVA_16", | ||||
|   "mixins": [ | ||||
|   ], | ||||
|   "client": [ | ||||
|       "ExampleMixin1_2" | ||||
|   ], | ||||
|   "injectors": { | ||||
|     "defaultRequire": 1 | ||||
|   } | ||||
| } | ||||
							
								
								
									
										119
									
								
								src/test/resources/projects/mixinApSimple/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								src/test/resources/projects/mixinApSimple/build.gradle
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,119 @@ | |||
| plugins { | ||||
| 	id 'fabric-loom' version '0.9.local' | ||||
| 	id 'maven-publish' | ||||
| } | ||||
| 
 | ||||
| sourceCompatibility = JavaVersion.VERSION_16 | ||||
| targetCompatibility = JavaVersion.VERSION_16 | ||||
| 
 | ||||
| archivesBaseName = project.archives_base_name | ||||
| version = project.mod_version | ||||
| group = project.maven_group | ||||
| 
 | ||||
| repositories { | ||||
| 	// Add repositories to retrieve artifacts from in here. | ||||
| 	// You should only use this when depending on other mods because | ||||
| 	// Loom adds the essential maven repositories to download Minecraft and libraries from automatically. | ||||
| 	// See https://docs.gradle.org/current/userguide/declaring_repositories.html | ||||
| 	// for more information about repositories. | ||||
| } | ||||
| 
 | ||||
| dependencies { | ||||
| 	// To change the versions see the gradle.properties file | ||||
| 	minecraft "com.mojang:minecraft:${project.minecraft_version}" | ||||
| 	mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" | ||||
| 	modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" | ||||
| 
 | ||||
| 	// Fabric API. This is technically optional, but you probably want it anyway. | ||||
| 	modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" | ||||
| 
 | ||||
| 	// PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. | ||||
| 	// You may need to force-disable transitiveness on them. | ||||
| } | ||||
| 
 | ||||
| sourceSets.register("mixin") { | ||||
| 	it.compileClasspath += sourceSets["main"].compileClasspath | ||||
| 	it.runtimeClasspath += sourceSets["main"].runtimeClasspath | ||||
| } | ||||
| sourceSets.register("mixin1") { | ||||
| 	it.compileClasspath += sourceSets["main"].compileClasspath | ||||
| 	it.runtimeClasspath += sourceSets["main"].runtimeClasspath | ||||
| } | ||||
| 
 | ||||
| processResources { | ||||
| 	inputs.property "version", project.version | ||||
| 
 | ||||
| 	filesMatching("fabric.mod.json") { | ||||
| 		expand "version": project.version | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| tasks.withType(JavaCompile).configureEach { | ||||
| 	// ensure that the encoding is set to UTF-8, no matter what the system default is | ||||
| 	// this fixes some edge cases with special characters not displaying correctly | ||||
| 	// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html | ||||
| 	// If Javadoc is generated, this must be specified in that task too. | ||||
| 	it.options.encoding = "UTF-8" | ||||
| 
 | ||||
| 	// Minecraft 1.17 (21w19a) upwards uses Java 16. | ||||
| 	it.options.release = 16 | ||||
| } | ||||
| 
 | ||||
| java { | ||||
| 	// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task | ||||
| 	// if it is present. | ||||
| 	// If you remove this line, sources will not be generated. | ||||
| 	withSourcesJar() | ||||
| } | ||||
| 
 | ||||
| loom { | ||||
| 	refmapName = "default-refmap0000.json" | ||||
| 	mixin { | ||||
| 		add(sourceSets["main"], "main-refmap0000.json") | ||||
| 		add(sourceSets["mixin"]) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| jar { | ||||
| 	from("LICENSE") { | ||||
| 		rename { "${it}_${project.archivesBaseName}"} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| tasks.register("mixinJar0", Jar.class) { | ||||
| 	it.archiveClassifier.set("mixin") | ||||
| 	it.from(sourceSets["mixin"].output) | ||||
| } | ||||
| 
 | ||||
| tasks.register("mixinJar1", Jar.class) { | ||||
| 	it.archiveClassifier.set("mixin1") | ||||
| 	it.from(sourceSets["mixin1"].output) | ||||
| } | ||||
| 
 | ||||
| assemble { | ||||
| 	dependsOn tasks["mixinJar0"] | ||||
| 	dependsOn tasks["mixinJar1"] | ||||
| } | ||||
| 
 | ||||
| // configure the maven publication | ||||
| publishing { | ||||
| 	publications { | ||||
| 		mavenJava(MavenPublication) { | ||||
| 			// add all the jars that should be included when publishing to maven | ||||
| 			artifact(remapJar) { | ||||
| 				builtBy remapJar | ||||
| 			} | ||||
| 			artifact(sourcesJar) { | ||||
| 				builtBy remapSourcesJar | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. | ||||
| 	repositories { | ||||
| 		// Add repositories to publish to here. | ||||
| 		// Notice: This block does NOT have the same function as the block in the top level. | ||||
| 		// The repositories here will be used for publishing your artifact, not for | ||||
| 		// retrieving dependencies. | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										16
									
								
								src/test/resources/projects/mixinApSimple/gradle.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/test/resources/projects/mixinApSimple/gradle.properties
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | |||
| # Done to increase the memory available to gradle. | ||||
| org.gradle.jvmargs=-Xmx1G | ||||
| 
 | ||||
| # Fabric Properties | ||||
| 	# check these on https://fabricmc.net/versions.html | ||||
| 	minecraft_version=1.17 | ||||
| 	yarn_mappings=1.17+build.13 | ||||
| 	loader_version=0.11.6 | ||||
| 
 | ||||
| # Mod Properties | ||||
| 	mod_version = 1.0.0 | ||||
| 	maven_group = com.example | ||||
| 	archives_base_name = fabric-example-mod | ||||
| 
 | ||||
| # Dependencies | ||||
| 	fabric_version=0.36.0+1.17 | ||||
							
								
								
									
										10
									
								
								src/test/resources/projects/mixinApSimple/settings.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/test/resources/projects/mixinApSimple/settings.gradle
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| pluginManagement { | ||||
|     repositories { | ||||
|         maven { | ||||
|             name = 'Fabric' | ||||
|             url = 'https://maven.fabricmc.net/' | ||||
|         } | ||||
|         gradlePluginPortal() | ||||
|         mavenLocal() | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| package net.fabricmc.example; | ||||
| 
 | ||||
| import net.fabricmc.api.ModInitializer; | ||||
| 
 | ||||
| public class ExampleMod implements ModInitializer { | ||||
| 	@Override | ||||
| 	public void onInitialize() { | ||||
| 		// This code runs as soon as Minecraft is in a mod-load-ready state. | ||||
| 		// However, some things (like resources) may still be uninitialized. | ||||
| 		// Proceed with mild caution. | ||||
| 
 | ||||
| 		System.out.println("Hello Fabric world!"); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,15 @@ | |||
| package net.fabricmc.example.mixin; | ||||
| 
 | ||||
| import net.minecraft.client.gui.screen.ChatScreen; | ||||
| import org.spongepowered.asm.mixin.Mixin; | ||||
| import org.spongepowered.asm.mixin.injection.At; | ||||
| import org.spongepowered.asm.mixin.injection.Inject; | ||||
| import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; | ||||
| 
 | ||||
| @Mixin(ChatScreen.class) | ||||
| public class ExampleMixin1 { | ||||
| 	@Inject(at = @At("HEAD"), method = "init()V") | ||||
| 	private void init(CallbackInfo info) { | ||||
| 		System.out.println("This line is printed by an example mod mixin!"); | ||||
| 	} | ||||
| } | ||||
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 453 B | 
|  | @ -0,0 +1,39 @@ | |||
| { | ||||
|   "schemaVersion": 1, | ||||
|   "id": "modid", | ||||
|   "version": "${version}", | ||||
| 
 | ||||
|   "name": "Example Mod", | ||||
|   "description": "This is an example description! Tell everyone what your mod is about!", | ||||
|   "authors": [ | ||||
|     "Me!" | ||||
|   ], | ||||
|   "contact": { | ||||
|     "homepage": "https://fabricmc.net/", | ||||
|     "sources": "https://github.com/FabricMC/fabric-example-mod" | ||||
|   }, | ||||
| 
 | ||||
|   "license": "CC0-1.0", | ||||
|   "icon": "assets/modid/icon.png", | ||||
| 
 | ||||
|   "environment": "*", | ||||
|   "entrypoints": { | ||||
|     "main": [ | ||||
|       "net.fabricmc.example.ExampleMod" | ||||
|     ] | ||||
|   }, | ||||
|   "mixins": [ | ||||
|     "main.mixins.json", | ||||
|     "m0.mixins.json" | ||||
|   ], | ||||
| 
 | ||||
|   "depends": { | ||||
|     "fabricloader": ">=0.11.3", | ||||
|     "fabric": "*", | ||||
|     "minecraft": "1.17.x", | ||||
|     "java": ">=16" | ||||
|   }, | ||||
|   "suggests": { | ||||
|     "another-mod": "*" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "required": true, | ||||
|   "minVersion": "0.8", | ||||
|   "package": "net.fabricmc.example.mixin", | ||||
|   "compatibilityLevel": "JAVA_16", | ||||
|   "mixins": [ | ||||
|   ], | ||||
|   "client": [ | ||||
|       "ExampleMixin1" | ||||
|   ], | ||||
|   "injectors": { | ||||
|     "defaultRequire": 1 | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,15 @@ | |||
| package net.fabricmc.example.mixin; | ||||
| 
 | ||||
| import net.minecraft.client.gui.screen.TitleScreen; | ||||
| import org.spongepowered.asm.mixin.Mixin; | ||||
| import org.spongepowered.asm.mixin.injection.At; | ||||
| import org.spongepowered.asm.mixin.injection.Inject; | ||||
| import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; | ||||
| 
 | ||||
| @Mixin(TitleScreen.class) | ||||
| public class ExampleMixin0 { | ||||
| 	@Inject(at = @At("HEAD"), method = "init()V") | ||||
| 	private void init(CallbackInfo info) { | ||||
| 		System.out.println("This line is printed by an example mod mixin!"); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "required": true, | ||||
|   "minVersion": "0.8", | ||||
|   "package": "net.fabricmc.example.mixin", | ||||
|   "compatibilityLevel": "JAVA_16", | ||||
|   "mixins": [ | ||||
|   ], | ||||
|   "client": [ | ||||
|       "ExampleMixin0" | ||||
|   ], | ||||
|   "injectors": { | ||||
|     "defaultRequire": 1 | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,15 @@ | |||
| package net.fabricmc.example.mixin; | ||||
| 
 | ||||
| import net.minecraft.client.gui.screen.TitleScreen; | ||||
| import org.spongepowered.asm.mixin.Mixin; | ||||
| import org.spongepowered.asm.mixin.injection.At; | ||||
| import org.spongepowered.asm.mixin.injection.Inject; | ||||
| import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; | ||||
| 
 | ||||
| @Mixin(TitleScreen.class) | ||||
| public class ExampleMixin1 { | ||||
| 	@Inject(at = @At("HEAD"), method = "init()V") | ||||
| 	private void init(CallbackInfo info) { | ||||
| 		System.out.println("This line is printed by an example mod mixin!"); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "required": true, | ||||
|   "minVersion": "0.8", | ||||
|   "package": "net.fabricmc.example.mixin", | ||||
|   "compatibilityLevel": "JAVA_16", | ||||
|   "mixins": [ | ||||
|   ], | ||||
|   "client": [ | ||||
|       "ExampleMixin0" | ||||
|   ], | ||||
|   "injectors": { | ||||
|     "defaultRequire": 1 | ||||
|   } | ||||
| } | ||||
		Loading…
	
		Reference in a new issue