Merge remote-tracking branch 'FabricMC/dev/0.9' into dev/0.9

# Conflicts:
#	src/main/java/net/fabricmc/loom/LoomGradleExtension.java
#	src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java
#	src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java
#	src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java
#	src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProviderImpl.java
#	src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java
#	src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java
#	src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java
This commit is contained in:
shedaniel
2021-07-20 18:03:33 +08:00
85 changed files with 2327 additions and 868 deletions

View File

@@ -15,8 +15,10 @@ import org.gradle.util.GradleVersion;
public class LoomGradlePluginBootstrap implements Plugin<PluginAware> {
private static final int MIN_SUPPORTED_MAJOR_GRADLE_VERSION = 7;
private static final int MIN_SUPPORTED_MAJOR_JAVA_VERSION = 16;
private static final int MIN_SUPPORTED_MAJOR_IDEA_VERSION = 2021;
private static final String PLUGIN_CLASS_NAME = "net.fabricmc.loom.LoomGradlePlugin";
private static final String IDEA_VERSION_PROP_KEY = "idea.version";
@Override
public void apply(PluginAware project) {
@@ -41,6 +43,10 @@ public class LoomGradlePluginBootstrap implements Plugin<PluginAware> {
}
}
if (!isValidIdeaRuntime()) {
errors.add(String.format("You are using an outdated version of intellij idea (%s). Intellij idea %d or higher is required.", System.getProperty(IDEA_VERSION_PROP_KEY), MIN_SUPPORTED_MAJOR_IDEA_VERSION));
}
if (!errors.isEmpty()) {
throw new UnsupportedOperationException(String.join("\n", errors));
}
@@ -57,6 +63,17 @@ public class LoomGradlePluginBootstrap implements Plugin<PluginAware> {
return getMajorGradleVersion() >= MIN_SUPPORTED_MAJOR_GRADLE_VERSION;
}
private static boolean isValidIdeaRuntime() {
String version = System.getProperty(IDEA_VERSION_PROP_KEY);
if (version == null) {
return true;
}
int ideaYear = Integer.parseInt(version.substring(0, version.indexOf(".")));
return ideaYear >= MIN_SUPPORTED_MAJOR_IDEA_VERSION;
}
private static int getMajorGradleVersion() {
String version = GradleVersion.current().getVersion();
return Integer.parseInt(version.substring(0, version.indexOf(".")));

View File

@@ -25,563 +25,84 @@
package net.fabricmc.loom;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.mercury.Mercury;
import org.gradle.api.Action;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.NamedDomainObjectProvider;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.plugins.BasePluginConvention;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import org.jetbrains.annotations.ApiStatus;
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
import net.fabricmc.loom.configuration.InstallerData;
import net.fabricmc.loom.configuration.LoomDependencyManager;
import net.fabricmc.loom.configuration.LoomProjectData;
import net.fabricmc.loom.configuration.ide.RunConfig;
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
import net.fabricmc.loom.configuration.launch.LaunchProviderSettings;
import net.fabricmc.loom.configuration.processors.JarProcessor;
import net.fabricmc.loom.configuration.processors.JarProcessorManager;
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
import net.fabricmc.loom.configuration.providers.forge.FieldMigratedMappingsProvider;
import net.fabricmc.loom.configuration.providers.forge.ForgeProvider;
import net.fabricmc.loom.configuration.providers.forge.ForgeUniversalProvider;
import net.fabricmc.loom.configuration.providers.forge.ForgeUserdevProvider;
import net.fabricmc.loom.configuration.providers.forge.McpConfigProvider;
import net.fabricmc.loom.configuration.providers.forge.PatchProvider;
import net.fabricmc.loom.configuration.providers.forge.SrgProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext;
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec;
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder;
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
import net.fabricmc.loom.util.ModPlatform;
import net.fabricmc.loom.util.function.LazyBool;
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 class LoomGradleExtension {
private static final String FORGE_PROPERTY = "loom.forge";
private static final String PLATFORM_PROPERTY = "loom.platform";
private static final String INCLUDE_PROPERTY = "loom.forge.include";
public String refmapName;
public String loaderLaunchMethod;
public boolean remapMod = true;
public String customManifest = null;
public File accessWidener = null;
public Set<File> accessTransformers = new HashSet<>();
public Function<String, Object> intermediaryUrl = mcVer -> "https://maven.fabricmc.net/net/fabricmc/intermediary/" + mcVer + "/intermediary-" + mcVer + "-v2.jar";
public boolean shareCaches = false;
public List<String> mixinConfigs = new ArrayList<>(); // FORGE: Passed to Minecraft
public boolean useFabricMixin = true; // FORGE: Use Fabric Mixin for better refmap resolutions
private final ConfigurableFileCollection unmappedMods;
private final ConfigurableFileCollection log4jConfigs;
final List<LoomDecompiler> decompilers = new ArrayList<>();
private final List<JarProcessor> jarProcessors = new ArrayList<>();
private boolean silentMojangMappingsLicense = false;
public Boolean generateSrgTiny = null;
// Not to be set in the build.gradle
private final Project project;
private List<String> dataGenMods = new ArrayList<>();
private LoomDependencyManager dependencyManager;
private JarProcessorManager jarProcessorManager;
private InstallerData installerData;
private MappingSet[] srcMappingCache = new MappingSet[2];
private Mercury[] srcMercuryCache = new Mercury[2];
private ModPlatform platform;
private final LazyBool supportsInclude;
private Set<File> mixinMappings = Collections.synchronizedSet(new HashSet<>());
private final List<String> tasksBeforeRun = Collections.synchronizedList(new ArrayList<>());
public final List<Supplier<SourceSet>> forgeLocalMods = Collections.synchronizedList(new ArrayList<>(Collections.singletonList(new Supplier<SourceSet>() {
@Override
public SourceSet get() {
return project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().getByName("main");
}
})));
@ApiStatus.Experimental
public final List<Consumer<RunConfig>> settingsPostEdit = new ArrayList<>();
@ApiStatus.Internal
private final LoomProjectData projectData;
private NamedDomainObjectContainer<RunConfigSettings> runConfigs;
private NamedDomainObjectContainer<LaunchProviderSettings> launchConfigs;
/**
* Loom will generate a new genSources task (with a new name, based off of {@link LoomDecompiler#name()})
* that uses the specified decompiler instead.
*/
public void addDecompiler(LoomDecompiler decompiler) {
decompilers.add(decompiler);
public interface LoomGradleExtension extends LoomGradleExtensionAPI {
static LoomGradleExtension get(Project project) {
return project.getExtensions().getByType(LoomGradleExtensionImpl.class);
}
/**
* Add a transformation over the mapped mc jar.
* Adding any jar processor will cause mapped mc jars to be stored per-project so that
* different transformation can be applied in different projects.
* This means remapping will need to be done individually per-project, which is slower when developing
* more than one project using the same minecraft version.
*/
public void addJarProcessor(JarProcessor processor) {
jarProcessors.add(processor);
}
LoomFiles getFiles();
public MappingSet getOrCreateSrcMappingCache(int id, Supplier<MappingSet> factory) {
if (id < 0 || id >= srcMappingCache.length) return factory.get();
return srcMappingCache[id] != null ? srcMappingCache[id] : (srcMappingCache[id] = factory.get());
}
NamedDomainObjectProvider<Configuration> createLazyConfiguration(String name);
public Mercury getOrCreateSrcMercuryCache(int id, Supplier<Mercury> factory) {
if (id < 0 || id >= srcMercuryCache.length) return factory.get();
return srcMercuryCache[id] != null ? srcMercuryCache[id] : (srcMercuryCache[id] = factory.get());
}
NamedDomainObjectProvider<Configuration> getLazyConfigurationProvider(String name);
public void localMods(Action<SourceSetConsumer> action) {
if (!isForge()) {
throw new UnsupportedOperationException("Not running with Forge support.");
}
MappingSet getOrCreateSrcMappingCache(int id, Supplier<MappingSet> factory);
action.execute(new SourceSetConsumer());
}
Mercury getOrCreateSrcMercuryCache(int id, Supplier<Mercury> factory);
public boolean isDataGenEnabled() {
return isForge() && !dataGenMods.isEmpty();
}
ConfigurableFileCollection getUnmappedModCollection();
public List<String> getDataGenMods() {
return dataGenMods;
}
void setInstallerData(InstallerData data);
public class SourceSetConsumer {
public void add(Object... sourceSets) {
for (Object sourceSet : sourceSets) {
if (sourceSet instanceof SourceSet) {
forgeLocalMods.add(() -> (SourceSet) sourceSet);
} else {
forgeLocalMods.add(() -> project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().findByName(String.valueOf(forgeLocalMods)));
}
}
}
}
InstallerData getInstallerData();
public void dataGen(Action<DataGenConsumer> action) {
if (!isForge()) {
throw new UnsupportedOperationException("Not running with Forge support.");
}
void setDependencyManager(LoomDependencyManager dependencyManager);
action.execute(new DataGenConsumer());
}
LoomDependencyManager getDependencyManager();
public class DataGenConsumer {
public void mod(String... modIds) {
dataGenMods.addAll(Arrays.asList(modIds));
void setJarProcessorManager(JarProcessorManager jarProcessorManager);
if (modIds.length > 0 && getRunConfigs().findByName("data") == null) {
getRunConfigs().create("data", RunConfigSettings::data);
}
}
}
JarProcessorManager getJarProcessorManager();
public void addTaskBeforeRun(String task) {
this.tasksBeforeRun.add(task);
}
public List<String> getTasksBeforeRun() {
return tasksBeforeRun;
}
public void mixinConfig(String... config) {
mixinConfigs.addAll(Arrays.asList(config));
}
public void silentMojangMappingsLicense() {
this.silentMojangMappingsLicense = true;
}
public boolean isSilentMojangMappingsLicenseEnabled() {
return silentMojangMappingsLicense;
}
public Dependency officialMojangMappings() {
return layered(LayeredMappingSpecBuilder::officialMojangMappings);
}
public Dependency layered(Action<LayeredMappingSpecBuilder> action) {
LayeredMappingSpecBuilder builder = new LayeredMappingSpecBuilder(this);
action.execute(builder);
LayeredMappingSpec builtSpec = builder.build();
return new LayeredMappingsDependency(new GradleMappingContext(project, () -> {
MinecraftVersionMeta versionInfo = getMinecraftProvider().getVersionInfo();
return "layers/" + versionInfo.id() + "_" + builtSpec.getVersion().replace("+", "_").replace(".", "_");
}), builtSpec, builtSpec.getVersion());
}
public LoomGradleExtension(Project project) {
this.project = project;
this.unmappedMods = project.files();
this.supportsInclude = new LazyBool(() -> Boolean.parseBoolean(Objects.toString(project.findProperty(INCLUDE_PROPERTY))));
this.runConfigs = project.container(RunConfigSettings.class,
baseName -> new RunConfigSettings(project, baseName));
this.launchConfigs = project.container(LaunchProviderSettings.class,
baseName -> new LaunchProviderSettings(project, baseName));
this.log4jConfigs = project.files(getDefaultLog4jConfigFile());
projectData = new LoomProjectData(project);
}
/**
* @see ConfigurableFileCollection#from(Object...)
* @deprecated use {@link #getUnmappedModCollection()}{@code .from()} instead
*/
@Deprecated
public void addUnmappedMod(Path file) {
getUnmappedModCollection().from(file);
}
/**
* @deprecated use {@link #getUnmappedModCollection()} instead
*/
@Deprecated
public List<Path> getUnmappedMods() {
return unmappedMods.getFiles().stream()
.map(File::toPath)
.collect(Collectors.toList());
}
public ConfigurableFileCollection getUnmappedModCollection() {
return unmappedMods;
}
public void setInstallerData(InstallerData data) {
this.installerData = data;
}
public InstallerData getInstallerData() {
return installerData;
}
public void accessWidener(Object file) {
this.accessWidener = project.file(file);
}
public void accessTransformer(Object file) {
this.accessTransformers.add(project.file(file));
}
public File getUserCache() {
File userCache = new File(project.getGradle().getGradleUserHomeDir(), "caches" + File.separator + "fabric-loom");
if (!userCache.exists()) {
userCache.mkdirs();
}
return userCache;
}
public File getRootProjectPersistentCache() {
File projectCache = new File(project.getRootProject().file(".gradle"), "loom-cache");
if (!projectCache.exists()) {
projectCache.mkdirs();
}
return projectCache;
}
public File getProjectPersistentCache() {
File projectCache = new File(project.file(".gradle"), "loom-cache");
if (!projectCache.exists()) {
projectCache.mkdirs();
}
return projectCache;
}
public File getRootProjectBuildCache() {
File projectCache = new File(project.getRootProject().getBuildDir(), "loom-cache");
if (!projectCache.exists()) {
projectCache.mkdirs();
}
return projectCache;
}
public File getProjectBuildCache() {
File projectCache = new File(project.getBuildDir(), "loom-cache");
if (!projectCache.exists()) {
projectCache.mkdirs();
}
return projectCache;
}
public File getRemappedModCache() {
File remappedModCache = new File(getRootProjectPersistentCache(), "remapped_mods");
if (!remappedModCache.exists()) {
remappedModCache.mkdir();
}
return remappedModCache;
}
public File getNestedModCache() {
File nestedModCache = new File(getRootProjectPersistentCache(), "nested_mods");
if (!nestedModCache.exists()) {
nestedModCache.mkdir();
}
return nestedModCache;
}
public File getNativesJarStore() {
File natives = new File(getUserCache(), "natives/jars");
if (!natives.exists()) {
natives.mkdirs();
}
return natives;
}
public File getNativesDirectory() {
if (project.hasProperty("fabric.loom.natives.dir")) {
return new File((String) project.property("fabric.loom.natives.dir"));
}
File natives = new File(getUserCache(), "natives/" + getMinecraftProvider().minecraftVersion());
if (!natives.exists()) {
natives.mkdirs();
}
return natives;
}
public boolean hasCustomNatives() {
return project.getProperties().get("fabric.loom.natives.dir") != null;
}
public File getDevLauncherConfig() {
return new File(getProjectPersistentCache(), "launch.cfg");
}
public String getLoaderLaunchMethod() {
return loaderLaunchMethod != null ? loaderLaunchMethod : "";
}
public LoomDependencyManager getDependencyManager() {
return dependencyManager;
}
public PatchProvider getPatchProvider() {
return getDependencyManager().getProvider(PatchProvider.class);
}
public MinecraftProviderImpl getMinecraftProvider() {
default MinecraftProviderImpl getMinecraftProvider() {
return getDependencyManager().getProvider(MinecraftProviderImpl.class);
}
public MinecraftMappedProvider getMinecraftMappedProvider() {
default MappingsProviderImpl getMappingsProvider() {
return getDependencyManager().getProvider(MappingsProviderImpl.class);
}
default MinecraftMappedProvider getMinecraftMappedProvider() {
return getMappingsProvider().mappedProvider;
}
public MappingsProviderImpl getMappingsProvider() {
return getDependencyManager().getProvider(isForge() ? FieldMigratedMappingsProvider.class : MappingsProviderImpl.class);
}
File getNextMixinMappings();
public McpConfigProvider getMcpConfigProvider() {
return getDependencyManager().getProvider(McpConfigProvider.class);
}
Set<File> getAllMixinMappings();
public SrgProvider getSrgProvider() {
return getDependencyManager().getProvider(SrgProvider.class);
}
boolean isRootProject();
public ForgeUniversalProvider getForgeUniversalProvider() {
return getDependencyManager().getProvider(ForgeUniversalProvider.class);
}
boolean isShareCaches();
public ForgeUserdevProvider getForgeUserdevProvider() {
return getDependencyManager().getProvider(ForgeUserdevProvider.class);
}
public ForgeProvider getForgeProvider() {
return getDependencyManager().getProvider(ForgeProvider.class);
}
public void setDependencyManager(LoomDependencyManager dependencyManager) {
this.dependencyManager = dependencyManager;
}
public JarProcessorManager getJarProcessorManager() {
return jarProcessorManager;
}
public void setJarProcessorManager(JarProcessorManager jarProcessorManager) {
this.jarProcessorManager = jarProcessorManager;
}
public List<JarProcessor> getJarProcessors() {
return jarProcessors;
}
public String getRefmapName() {
if (refmapName == null || refmapName.isEmpty()) {
String defaultRefmapName;
if (isRootProject()) {
defaultRefmapName = project.getConvention().getPlugin(BasePluginConvention.class).getArchivesBaseName() + "-refmap.json";
} else {
defaultRefmapName = project.getConvention().getPlugin(BasePluginConvention.class).getArchivesBaseName() + "-" + project.getPath().replaceFirst(":", "").replace(':', '_') + "-refmap.json";
}
project.getLogger().info("Could not find refmap definition, will be using default name: " + defaultRefmapName);
refmapName = defaultRefmapName;
}
return refmapName;
}
public boolean ideSync() {
default boolean ideSync() {
return Boolean.parseBoolean(System.getProperty("idea.sync.active", "false"));
}
// Ideally this should use maven, but this is a lot easier
public Function<String, String> getIntermediaryUrl() {
// Done like this to work around this possibly not being a java string...
return s -> intermediaryUrl.apply(s).toString();
default String getIntermediaryUrl(String minecraftVersion) {
// 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);
}
public boolean isRootProject() {
return project.getRootProject() == project;
}
public LoomGradleExtension getRootGradleExtension() {
if (isRootProject()) {
return this;
}
return project.getRootProject().getExtensions().getByType(LoomGradleExtension.class);
}
public LoomGradleExtension getSharedGradleExtension() {
return isShareCaches() ? getRootGradleExtension() : this;
}
public boolean isShareCaches() {
return shareCaches;
}
@ApiStatus.Experimental
public ModPlatform getPlatform() {
if (platform == null) {
Object platformProperty = project.findProperty(PLATFORM_PROPERTY);
if (platformProperty != null) {
return platform = ModPlatform.valueOf(Objects.toString(platformProperty).toUpperCase(Locale.ROOT));
}
Object forgeProperty = project.findProperty(FORGE_PROPERTY);
if (forgeProperty != null) {
project.getLogger().warn("Project " + project.getPath() + " is using property " + FORGE_PROPERTY + " to enable forge mode. Please use '" + PLATFORM_PROPERTY + " = forge' instead!");
return platform = Boolean.parseBoolean(Objects.toString(forgeProperty)) ? ModPlatform.FORGE : ModPlatform.FABRIC;
}
platform = ModPlatform.FABRIC;
}
return platform;
}
public boolean isForge() {
return getPlatform() == ModPlatform.FORGE;
}
public boolean supportsInclude() {
return !isForge() || supportsInclude.getAsBoolean();
}
public boolean shouldGenerateSrgTiny() {
if (generateSrgTiny != null) {
return generateSrgTiny;
}
return isForge();
}
// Creates a new file each time its called, this is then held onto later when remapping the output jar
// Required as now when using parallel builds the old single file could be written by another sourceset compile task
public synchronized File getNextMixinMappings() {
File mixinMapping = new File(getProjectBuildCache(), "mixin-map-" + getMinecraftProvider().minecraftVersion() + "-" + getMappingsProvider().mappingsVersion + "." + mixinMappings.size() + ".tiny");
mixinMappings.add(mixinMapping);
return mixinMapping;
}
public Set<File> getAllMixinMappings() {
return Collections.unmodifiableSet(mixinMappings);
}
public List<LoomDecompiler> getDecompilers() {
return decompilers;
}
public File getDefaultLog4jConfigFile() {
return new File(getProjectPersistentCache(), "log4j.xml");
}
public File getUnpickLoggingConfigFile() {
return new File(getProjectPersistentCache(), "unpick-logging.properties");
}
public ConfigurableFileCollection getLog4jConfigs() {
return log4jConfigs;
}
public void runs(Action<NamedDomainObjectContainer<RunConfigSettings>> action) {
action.execute(runConfigs);
}
public void launches(Action<NamedDomainObjectContainer<LaunchProviderSettings>> action) {
action.execute(launchConfigs);
}
public NamedDomainObjectContainer<RunConfigSettings> getRunConfigs() {
return runConfigs;
}
public NamedDomainObjectContainer<LaunchProviderSettings> getLaunchConfigs() {
return launchConfigs;
}
@ApiStatus.Internal
public LoomProjectData getProjectData() {
return projectData;
}
MixinApExtension getMixinApExtension();
}

View File

@@ -45,6 +45,8 @@ import net.fabricmc.loom.configuration.MavenPublication;
import net.fabricmc.loom.configuration.ide.IdeConfiguration;
import net.fabricmc.loom.configuration.providers.mappings.MappingsCache;
import net.fabricmc.loom.decompilers.DecompilerConfiguration;
import net.fabricmc.loom.extension.LoomGradleExtensionImpl;
import net.fabricmc.loom.extension.LoomFilesImpl;
import net.fabricmc.loom.task.LoomTasks;
public class LoomGradlePlugin implements BootstrappedPlugin {
@@ -85,7 +87,7 @@ public class LoomGradlePlugin implements BootstrappedPlugin {
project.apply(ImmutableMap.of("plugin", "idea"));
// Setup extensions, loom shadows minecraft
project.getExtensions().create("minecraft", LoomGradleExtension.class, project);
project.getExtensions().create(LoomGradleExtension.class, "minecraft", LoomGradleExtensionImpl.class, project, new LoomFilesImpl(project));
project.getExtensions().add("loom", project.getExtensions().getByName("minecraft"));
project.getExtensions().create("fabricApi", FabricApiExtension.class, project);

View File

@@ -0,0 +1,91 @@
/*
* 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 java.io.File;
import java.util.List;
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;
import net.fabricmc.loom.configuration.processors.JarProcessor;
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder;
/**
* This is the public api available exposed to build scripts.
*/
public interface LoomGradleExtensionAPI {
File getAccessWidener();
void setAccessWidener(Object file);
void setShareCaches(boolean shareCaches);
boolean isShareCaches();
default void shareCaches() {
setShareCaches(true);
}
List<LoomDecompiler> getDecompilers();
void addDecompiler(LoomDecompiler decompiler);
List<JarProcessor> getJarProcessors();
void addJarProcessor(JarProcessor processor);
ConfigurableFileCollection getLog4jConfigs();
default Dependency officialMojangMappings() {
return layered(LayeredMappingSpecBuilder::officialMojangMappings);
}
Dependency layered(Action<LayeredMappingSpecBuilder> action);
String getRefmapName();
void setRefmapName(String refmapName);
boolean isRemapMod();
void setRemapMod(boolean remapMod);
void runs(Action<NamedDomainObjectContainer<RunConfigSettings>> action);
NamedDomainObjectContainer<RunConfigSettings> getRunConfigs();
@ApiStatus.Experimental
void mixin(Action<MixinApExtensionAPI> action);
void setCustomManifest(String customManifest);
String getCustomManifest();
}

View 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);
}

View File

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

View File

@@ -51,7 +51,6 @@ import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.configuration.LoomProjectData;
import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
import net.fabricmc.loom.configuration.mods.ModProcessor;
import net.fabricmc.loom.configuration.processors.dependency.ModDependencyInfo;
@@ -76,13 +75,11 @@ public class ModCompileRemapper {
DependencyHandler dependencies = project.getDependencies();
boolean refreshDeps = LoomGradlePlugin.refreshDeps;
final File modStore = extension.getRemappedModCache();
final File modStore = extension.getFiles().getRemappedModCache();
final RemapData remapData = new RemapData(mappingsSuffix, modStore);
final LoomProjectData data = extension.getProjectData();
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
data.getLazyConfigurationProvider(entry.getRemappedConfiguration()).configure(remappedConfig -> {
extension.getLazyConfigurationProvider(entry.getRemappedConfiguration()).configure(remappedConfig -> {
Configuration sourceConfig = project.getConfigurations().getByName(entry.sourceConfiguration());
Configuration regularConfig = project.getConfigurations().getByName(entry.getTargetConfiguration(project.getConfigurations()));

View File

@@ -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 = project.getExtensions().getByType(LoomGradleExtension.class);
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);
@@ -87,10 +97,10 @@ public abstract class AnnotationProcessorInvoker<T extends Task> {
public void configureMixin() {
ConfigurationContainer configs = project.getConfigurations();
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
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(
@@ -109,14 +119,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"));
}
}

View File

@@ -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";

View File

@@ -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 = project.getExtensions().getByType(LoomGradleExtension.class);
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;
}
}

View File

@@ -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,
// 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));
super(
project,
// Scala just uses the java AP configuration afaik. This of course assumes the java AP also gets configured.
ImmutableList.of(),
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();
}
}

View File

@@ -157,8 +157,8 @@ public final class NestedDependencyProvider implements NestedJarProvider {
//A lib that doesnt have a mod.json, we turn it into a fake mod
if (!ZipUtil.containsEntry(file, "fabric.mod.json")) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
File tempDir = new File(extension.getUserCache(), "temp/modprocessing");
LoomGradleExtension extension = LoomGradleExtension.get(project);
File tempDir = new File(extension.getFiles().getUserCache(), "temp/modprocessing");
if (!tempDir.exists()) {
tempDir.mkdirs();

View File

@@ -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;
@@ -57,11 +58,11 @@ public final class CompileConfiguration {
public static void setupConfigurations(Project project) {
final ConfigurationContainer configurations = project.getConfigurations();
LoomProjectData data = project.getExtensions().getByType(LoomGradleExtension.class).getProjectData();
LoomGradleExtension extension = LoomGradleExtension.get(project);
project.afterEvaluate(project1 -> {
if (project.getExtensions().getByType(LoomGradleExtension.class).shouldGenerateSrgTiny()) {
data.createLazyConfiguration(Constants.Configurations.SRG).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.SRG).configure(configuration -> configuration.setTransitive(false));
}
if (project.getExtensions().getByType(LoomGradleExtension.class).isDataGenEnabled()) {
@@ -71,21 +72,21 @@ public final class CompileConfiguration {
}
});
data.createLazyConfiguration(Constants.Configurations.MOD_COMPILE_CLASSPATH).configure(configuration -> configuration.setTransitive(true));
data.createLazyConfiguration(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED).configure(configuration -> configuration.setTransitive(false));
data.createLazyConfiguration(Constants.Configurations.MINECRAFT_NAMED).configure(configuration -> configuration.setTransitive(false)); // The launchers do not recurse dependencies
data.createLazyConfiguration(Constants.Configurations.MINECRAFT_DEPENDENCIES).configure(configuration -> configuration.setTransitive(false));
data.createLazyConfiguration(Constants.Configurations.LOADER_DEPENDENCIES).configure(configuration -> configuration.setTransitive(false));
data.createLazyConfiguration(Constants.Configurations.MINECRAFT).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.MOD_COMPILE_CLASSPATH).configure(configuration -> configuration.setTransitive(true));
extension.createLazyConfiguration(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.MINECRAFT_NAMED).configure(configuration -> configuration.setTransitive(false)); // The launchers do not recurse dependencies
extension.createLazyConfiguration(Constants.Configurations.MINECRAFT_DEPENDENCIES).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.LOADER_DEPENDENCIES).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.MINECRAFT).configure(configuration -> configuration.setTransitive(false));
if (project.getExtensions().getByType(LoomGradleExtension.class).isForge()) {
data.createLazyConfiguration(Constants.Configurations.FORGE).configure(configuration -> configuration.setTransitive(false));
data.createLazyConfiguration(Constants.Configurations.FORGE_USERDEV).configure(configuration -> configuration.setTransitive(false));
data.createLazyConfiguration(Constants.Configurations.FORGE_INSTALLER).configure(configuration -> configuration.setTransitive(false));
data.createLazyConfiguration(Constants.Configurations.FORGE_UNIVERSAL).configure(configuration -> configuration.setTransitive(false));
data.createLazyConfiguration(Constants.Configurations.FORGE_DEPENDENCIES).configure(configuration -> configuration.setTransitive(false));
data.createLazyConfiguration(Constants.Configurations.FORGE_NAMED).configure(configuration -> configuration.setTransitive(false));
data.createLazyConfiguration(Constants.Configurations.MCP_CONFIG).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.FORGE).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.FORGE_USERDEV).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.FORGE_INSTALLER).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.FORGE_UNIVERSAL).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.FORGE_DEPENDENCIES).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.FORGE_NAMED).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.MCP_CONFIG).configure(configuration -> configuration.setTransitive(false));
extendsFrom(Constants.Configurations.MINECRAFT_DEPENDENCIES, Constants.Configurations.FORGE_DEPENDENCIES, project);
@@ -96,24 +97,24 @@ public final class CompileConfiguration {
}
if (project.getExtensions().getByType(LoomGradleExtension.class).supportsInclude()) {
data.createLazyConfiguration(Constants.Configurations.INCLUDE).configure(configuration -> configuration.setTransitive(false)); // Dont get transitive deps
extension.createLazyConfiguration(Constants.Configurations.INCLUDE).configure(configuration -> configuration.setTransitive(false)); // Dont get transitive deps
}
data.createLazyConfiguration(Constants.Configurations.MAPPING_CONSTANTS);
extension.createLazyConfiguration(Constants.Configurations.MAPPING_CONSTANTS);
extendsFrom(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, Constants.Configurations.MAPPING_CONSTANTS, project);
data.createLazyConfiguration(Constants.Configurations.MAPPINGS);
data.createLazyConfiguration(Constants.Configurations.MAPPINGS_FINAL);
data.createLazyConfiguration(Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES);
data.createLazyConfiguration(Constants.Configurations.UNPICK_CLASSPATH);
extension.createLazyConfiguration(Constants.Configurations.MAPPINGS);
extension.createLazyConfiguration(Constants.Configurations.MAPPINGS_FINAL);
extension.createLazyConfiguration(Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES);
extension.createLazyConfiguration(Constants.Configurations.UNPICK_CLASSPATH);
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
data.createLazyConfiguration(entry.sourceConfiguration())
extension.createLazyConfiguration(entry.sourceConfiguration())
.configure(configuration -> configuration.setTransitive(true));
// Don't get transitive deps of already remapped mods
data.createLazyConfiguration(entry.getRemappedConfiguration())
extension.createLazyConfiguration(entry.getRemappedConfiguration())
.configure(configuration -> configuration.setTransitive(false));
extendsFrom(entry.getTargetConfiguration(configurations), entry.getRemappedConfiguration(), project);
@@ -152,7 +153,7 @@ public final class CompileConfiguration {
});
p.afterEvaluate(project -> {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
LoomDependencyManager dependencyManager = new LoomDependencyManager();
extension.setDependencyManager(dependencyManager);
@@ -187,7 +188,7 @@ public final class CompileConfiguration {
GenVsCodeProjectTask.generate(project);
// Enables the default mod remapper
if (extension.remapMod) {
if (extension.isRemapMod()) {
RemapConfiguration.setupDefaultRemap(project);
} else {
Jar jarTask = (Jar) project.getTasks().getByName("jar");
@@ -200,6 +201,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")) {

View File

@@ -49,6 +49,7 @@ import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.extension.LoomFiles;
public abstract class DependencyProvider {
private LoomDependencyManager dependencyManager;
@@ -57,7 +58,7 @@ public abstract class DependencyProvider {
public DependencyProvider(Project project) {
this.project = project;
this.extension = project.getExtensions().getByType(LoomGradleExtension.class);
this.extension = LoomGradleExtension.get(project);
}
public abstract void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception;
@@ -88,6 +89,10 @@ public abstract class DependencyProvider {
return extension;
}
public LoomFiles getDirectories() {
return getExtension().getFiles();
}
public boolean isRefreshDeps() {
return LoomGradlePlugin.refreshDeps;
}

View File

@@ -103,9 +103,17 @@ public class FabricApiExtension {
}
private File getApiMavenPom(String fabricApiVersion) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
File mavenPom = new File(extension.getUserCache(), "fabric-api/" + fabricApiVersion + ".pom");
File mavenPom = new File(extension.getFiles().getUserCache(), "fabric-api/" + fabricApiVersion + ".pom");
if (project.getGradle().getStartParameter().isOffline()) {
if (!mavenPom.exists()) {
throw new RuntimeException("Cannot retrieve fabric-api pom due to being offline");
}
return mavenPom;
}
try {
URL url = new URL(String.format("https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api/%1$s/fabric-api-%1$s.pom", fabricApiVersion));

View File

@@ -43,7 +43,7 @@ public final record JarManifestConfiguration(Project project) {
return;
}
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
Attributes attributes = manifest.getMainAttributes();
var tinyRemapperVersion = Optional.ofNullable(TinyRemapper.class.getPackage().getImplementationVersion());
@@ -79,7 +79,7 @@ public final record JarManifestConfiguration(Project project) {
}
private Optional<String> getLoaderVersion() {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
if (extension.getInstallerData() == null) {
project.getLogger().warn("Could not determine fabric loader version for jar manifest");

View File

@@ -89,7 +89,7 @@ public class LoomDependencyManager {
MappingsProviderImpl mappingsProvider = null;
project.getLogger().info(":setting up loom dependencies");
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
Map<String, ProviderList> providerListMap = new HashMap<>();
List<ProviderList> targetProviders = new ArrayList<>();
@@ -178,7 +178,7 @@ public class LoomDependencyManager {
}
private static void handleInstallerJson(JsonObject jsonObject, Project project) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
JsonObject libraries = jsonObject.get("libraries").getAsJsonObject();
Configuration loaderDepsConfig = project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES);

View File

@@ -1,70 +0,0 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016-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.configuration;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import org.gradle.api.NamedDomainObjectProvider;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.jetbrains.annotations.ApiStatus;
@ApiStatus.Internal
/**
* This class is stored in the gradle extension, and should not be used outside of loom.
* It contains data/info related to the current project
*/
public final class LoomProjectData {
private final Project project;
private final Map<String, NamedDomainObjectProvider<Configuration>> lazyConfigurations = new HashMap<>();
public LoomProjectData(Project project) {
this.project = Objects.requireNonNull(project);
}
public NamedDomainObjectProvider<Configuration> createLazyConfiguration(String name) {
NamedDomainObjectProvider<Configuration> provider = project.getConfigurations().register(name);
if (lazyConfigurations.containsKey(name)) {
throw new IllegalStateException("Duplicate configuration name" + name);
}
lazyConfigurations.put(name, provider);
return provider;
}
public NamedDomainObjectProvider<Configuration> getLazyConfigurationProvider(String name) {
NamedDomainObjectProvider<Configuration> provider = lazyConfigurations.get(name);
if (provider == null) {
throw new NullPointerException("Could not find provider with name: " + name);
}
return provider;
}
}

View File

@@ -65,7 +65,7 @@ public class RemapConfiguration {
// isDefaultRemap is set to true for the standard remap task, some defaults are left out when this is false.
private static void setupRemap(Project project, boolean isDefaultRemap, String jarTaskName, String sourcesJarTaskName, String remapJarTaskName, String remapSourcesJarTaskName, String remapAllJarsTaskName, String remapAllSourcesTaskName) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
AbstractArchiveTask jarTask = (AbstractArchiveTask) project.getTasks().getByName(jarTaskName);
RemapJarTask remapJarTask = (RemapJarTask) project.getTasks().findByName(remapJarTaskName);

View File

@@ -72,15 +72,15 @@ public class AccessWidenerJarProcessor implements JarProcessor {
@Override
public void setup() {
LoomGradleExtension loomGradleExtension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension loomGradleExtension = LoomGradleExtension.get(project);
if (!loomGradleExtension.accessWidener.exists()) {
throw new RuntimeException("Could not find access widener file @ " + loomGradleExtension.accessWidener.getAbsolutePath());
if (!loomGradleExtension.getAccessWidener().exists()) {
throw new RuntimeException("Could not find access widener file @ " + loomGradleExtension.getAccessWidener().getAbsolutePath());
}
inputHash = Checksum.sha256(loomGradleExtension.accessWidener);
inputHash = Checksum.sha256(loomGradleExtension.getAccessWidener());
try (BufferedReader reader = new BufferedReader(new FileReader(loomGradleExtension.accessWidener))) {
try (BufferedReader reader = new BufferedReader(new FileReader(loomGradleExtension.getAccessWidener()))) {
accessWidenerReader.read(reader);
} catch (IOException e) {
throw new RuntimeException("Failed to read project access widener file");

View File

@@ -28,10 +28,8 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Consumer;
@@ -41,7 +39,6 @@ import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@@ -53,7 +50,6 @@ import org.w3c.dom.Element;
import org.w3c.dom.Node;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.OperatingSystem;
public class RunConfig {
@@ -131,13 +127,8 @@ public class RunConfig {
runConfig.vmArgs = "";
runConfig.programArgs = "";
if ("launchwrapper".equals(extension.getLoaderLaunchMethod())) {
runConfig.mainClass = "net.minecraft.launchwrapper.Launch"; // TODO What about custom tweakers for run configs?
runConfig.programArgs += "--tweakClass " + ("client".equals(environment) ? Constants.LaunchWrapper.DEFAULT_FABRIC_CLIENT_TWEAKER : Constants.LaunchWrapper.DEFAULT_FABRIC_SERVER_TWEAKER);
} else {
runConfig.mainClass = "net.fabricmc.devlaunchinjector.Main";
runConfig.vmArgs = "-XX:+ShowCodeDetailsInExceptionMessages -Dfabric.dli.config=" + encodeEscaped(extension.getDevLauncherConfig().getAbsolutePath()) + " -Dfabric.dli.env=" + environment.toLowerCase();
}
runConfig.mainClass = "net.fabricmc.devlaunchinjector.Main";
runConfig.vmArgs = "-XX:+ShowCodeDetailsInExceptionMessages -Dfabric.dli.config=" + encodeEscaped(extension.getFiles().getDevLauncherConfig().getAbsolutePath()) + " -Dfabric.dli.env=" + environment.toLowerCase();
if (extension.isForge()) {
List<String> modClasses = new ArrayList<>();
@@ -155,35 +146,6 @@ public class RunConfig {
runConfig.envVariables.put("MOD_CLASSES", String.join(File.pathSeparator, modClasses));
}
if (extension.getLoaderLaunchMethod().equals("launchwrapper")) {
// if installer.json found...
JsonObject installerJson = extension.getInstallerData().installerJson();
if (installerJson != null) {
List<String> sideKeys = ImmutableList.of(environment, "common");
// copy launchwrapper tweakers
if (installerJson.has("launchwrapper")) {
JsonObject launchwrapperJson = installerJson.getAsJsonObject("launchwrapper");
if (launchwrapperJson.has("tweakers")) {
JsonObject tweakersJson = launchwrapperJson.getAsJsonObject("tweakers");
StringBuilder builder = new StringBuilder();
for (String s : sideKeys) {
if (tweakersJson.has(s)) {
for (JsonElement element : tweakersJson.getAsJsonArray(s)) {
builder.append(" --tweakClass ").append(element.getAsString());
}
}
}
runConfig.programArgs += builder.toString();
}
}
}
}
}
// Turns camelCase/PascalCase into Capital Case
@@ -197,7 +159,7 @@ public class RunConfig {
}
public static RunConfig runConfig(Project project, RunConfigSettings settings) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
String name = settings.getName();
String configName = settings.getConfigName();
@@ -325,11 +287,6 @@ public class RunConfig {
return mainClassName;
}
// Fallback to default class names, happens when in a loader dev env
if ("launchwrapper".equals(extension.getLoaderLaunchMethod())) {
return "net.minecraft.launchwrapper.Launch";
}
return defaultMainClass;
}

View File

@@ -100,7 +100,7 @@ public final class RunConfigSettings implements Named {
public RunConfigSettings(Project project, String baseName) {
this.baseName = baseName;
this.project = project;
this.extension = project.getExtensions().getByType(LoomGradleExtension.class);
this.extension = LoomGradleExtension.get(project);
this.ideConfigGenerated = extension.isRootProject();
source("main");

View File

@@ -37,7 +37,7 @@ import net.fabricmc.loom.configuration.providers.minecraft.assets.MinecraftAsset
public class SetupIntelijRunConfigs {
public static void setup(Project project) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
File projectDir = project.getRootProject().file(".idea");
@@ -54,7 +54,7 @@ public class SetupIntelijRunConfigs {
private static void generate(Project project) throws IOException {
Project rootProject = project.getRootProject();
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
if (extension.ideSync()) {
//Ensures the assets are downloaded when idea is syncing a project

View File

@@ -137,7 +137,7 @@ public class ModProcessor {
}
private static void remapJars(Project project, List<ModDependencyInfo> processList) throws IOException {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
String fromM = extension.isForge() ? "srg" : "intermediary";
String toM = "named";
@@ -277,28 +277,15 @@ public class ModProcessor {
public static JsonObject readInstallerJson(File file, Project project) {
try {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
String launchMethod = extension.getLoaderLaunchMethod();
LoomGradleExtension extension = LoomGradleExtension.get(project);
String jsonStr;
try (JarFile jarFile = new JarFile(file)) {
ZipEntry entry = null;
if (!launchMethod.isEmpty()) {
entry = jarFile.getEntry("fabric-installer." + launchMethod + ".json");
if (entry == null) {
project.getLogger().warn("Could not find loader launch method '" + launchMethod + "', falling back");
}
}
ZipEntry entry = jarFile.getEntry("fabric-installer.json");
if (entry == null) {
entry = jarFile.getEntry("fabric-installer.json");
if (entry == null) {
return null;
}
return null;
}
try (InputStream inputstream = jarFile.getInputStream(entry)) {

View File

@@ -72,7 +72,7 @@ public class MinecraftProcessedProvider extends MinecraftMappedProvider {
}
private void invalidateJars() {
File dir = getJarDirectory(getExtension().getUserCache(), projectMappedClassifier);
File dir = getJarDirectory(getExtension().getFiles().getUserCache(), projectMappedClassifier);
if (dir.exists()) {
getProject().getLogger().warn("Invalidating project jars");
@@ -89,7 +89,7 @@ public class MinecraftProcessedProvider extends MinecraftMappedProvider {
public void initFiles(MinecraftProviderImpl minecraftProvider, MappingsProviderImpl mappingsProvider) {
super.initFiles(minecraftProvider, mappingsProvider);
projectMappedJar = new File(getJarDirectory(getExtension().getRootProjectPersistentCache(), projectMappedClassifier), "minecraft-" + getJarVersionString(projectMappedClassifier) + ".jar");
projectMappedJar = new File(getJarDirectory(getExtension().getFiles().getRootProjectPersistentCache(), projectMappedClassifier), "minecraft-" + getJarVersionString(projectMappedClassifier) + ".jar");
}
@Override

View File

@@ -59,13 +59,13 @@ public class LaunchProvider extends DependencyProvider {
.property("fabric.remapClasspathFile", getRemapClasspathFile().getAbsolutePath())
.property("log4j.configurationFile", getAllLog4JConfigFiles())
.property("client", "java.library.path", getExtension().getNativesDirectory().getAbsolutePath())
.property("client", "org.lwjgl.librarypath", getExtension().getNativesDirectory().getAbsolutePath())
.property("client", "java.library.path", getDirectories().getNativesDirectory(getExtension().getMinecraftProvider()).getAbsolutePath())
.property("client", "org.lwjgl.librarypath", getDirectories().getNativesDirectory(getExtension().getMinecraftProvider()).getAbsolutePath())
.argument("client", "--assetIndex")
.argument("client", getExtension().getMinecraftProvider().getVersionInfo().assetIndex().fabricId(getExtension().getMinecraftProvider().minecraftVersion()))
.argument("client", "--assetsDir")
.argument("client", new File(getExtension().getUserCache(), "assets").getAbsolutePath());
.argument("client", new File(getDirectories().getUserCache(), "assets").getAbsolutePath());
if (getExtension().isForge()) {
launchConfig
@@ -127,7 +127,7 @@ public class LaunchProvider extends DependencyProvider {
}
writeLog4jConfig();
FileUtils.writeStringToFile(getExtension().getDevLauncherConfig(), launchConfig.asString(), StandardCharsets.UTF_8);
FileUtils.writeStringToFile(getDirectories().getDevLauncherConfig(), launchConfig.asString(), StandardCharsets.UTF_8);
addDependency(Constants.Dependencies.DEV_LAUNCH_INJECTOR + Constants.Dependencies.Versions.DEV_LAUNCH_INJECTOR, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES);
addDependency(Constants.Dependencies.TERMINAL_CONSOLE_APPENDER + Constants.Dependencies.Versions.TERMINAL_CONSOLE_APPENDER, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES);
@@ -143,7 +143,7 @@ public class LaunchProvider extends DependencyProvider {
}
private File getLog4jConfigFile() {
return getExtension().getDefaultLog4jConfigFile();
return getDirectories().getDefaultLog4jConfigFile();
}
private String getAllLog4JConfigFiles() {
@@ -153,7 +153,7 @@ public class LaunchProvider extends DependencyProvider {
}
private File getRemapClasspathFile() {
return new File(getExtension().getDevLauncherConfig().getParentFile(), "remapClasspath.txt");
return new File(getDirectories().getDevLauncherConfig().getParentFile(), "remapClasspath.txt");
}
private void writeLog4jConfig() {

View File

@@ -59,6 +59,7 @@ public class MinecraftProviderImpl extends DependencyProvider implements Minecra
public File minecraftServerJar;
private File minecraftMergedJar;
private File versionManifestJson;
private File experimentalVersionsJson;
private String jarSuffix = "";
public MinecraftProviderImpl(Project project) {
@@ -117,17 +118,20 @@ public class MinecraftProviderImpl extends DependencyProvider implements Minecra
}
private void initFiles() {
minecraftJson = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-info.json");
minecraftClientJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-client.jar");
minecraftServerJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-server.jar");
minecraftMergedJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar");
versionManifestJson = new File(getExtension().getUserCache(), "version_manifest.json");
minecraftJson = new File(getDirectories().getUserCache(), "minecraft-" + minecraftVersion + "-info.json");
minecraftClientJar = new File(getDirectories().getUserCache(), "minecraft-" + minecraftVersion + "-client.jar");
minecraftServerJar = new File(getDirectories().getUserCache(), "minecraft-" + minecraftVersion + "-server.jar");
minecraftMergedJar = new File(getDirectories().getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar");
versionManifestJson = new File(getDirectories().getUserCache(), "version_manifest.json");
experimentalVersionsJson = new File(getDirectories().getUserCache(), "experimental_version_manifest.json");
}
public void deleteFiles() {
DownloadUtil.delete(minecraftClientJar);
DownloadUtil.delete(minecraftServerJar);
DownloadUtil.delete(minecraftMergedJar);
DownloadUtil.delete(versionManifestJson);
DownloadUtil.delete(experimentalVersionsJson);
}
private void downloadMcJson(boolean offline) throws IOException {
@@ -155,16 +159,20 @@ public class MinecraftProviderImpl extends DependencyProvider implements Minecra
Optional<ManifestVersion.Versions> optionalVersion = Optional.empty();
if (getExtension().customManifest != null) {
if (getExtension().getCustomManifest() != null) {
ManifestVersion.Versions customVersion = new ManifestVersion.Versions();
customVersion.id = minecraftVersion;
customVersion.url = getExtension().customManifest;
customVersion.url = getExtension().getCustomManifest();
optionalVersion = Optional.of(customVersion);
getProject().getLogger().lifecycle("Using custom minecraft manifest");
}
if (!optionalVersion.isPresent()) {
if (optionalVersion.isEmpty()) {
optionalVersion = mcManifest.versions().stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst();
if (optionalVersion.isEmpty()) {
optionalVersion = findExperimentalVersion(offline);
}
}
if (optionalVersion.isPresent()) {
@@ -194,8 +202,31 @@ public class MinecraftProviderImpl extends DependencyProvider implements Minecra
}
}
// This attempts to find the version from fabric's own fallback version manifest json.
private Optional<ManifestVersion.Versions> findExperimentalVersion(boolean offline) throws IOException {
if (offline) {
if (!experimentalVersionsJson.exists()) {
getProject().getLogger().warn("Skipping download of experimental versions jsons due to being offline.");
return Optional.empty();
}
} else {
DownloadUtil.downloadIfChanged(new URL(Constants.EXPERIMENTAL_VERSIONS), experimentalVersionsJson, getProject().getLogger());
}
String expVersionManifest = Files.asCharSource(experimentalVersionsJson, StandardCharsets.UTF_8).read();
ManifestVersion expManifest = LoomGradlePlugin.OBJECT_MAPPER.readValue(expVersionManifest, ManifestVersion.class);
var result = expManifest.versions().stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst();
if (result.isPresent()) {
getProject().getLogger().lifecycle("Using fallback experimental version {}", minecraftVersion);
}
return result;
}
private boolean hasRecentValidManifest() throws IOException {
if (getExtension().customManifest != null) {
if (getExtension().getCustomManifest() != null) {
return false;
}

View File

@@ -41,7 +41,7 @@ public class GradleMappingContext implements MappingContext {
public GradleMappingContext(Project project, Supplier<String> workingDirName) {
this.project = project;
this.extension = project.getExtensions().getByType(LoomGradleExtension.class);
this.extension = LoomGradleExtension.get(project);
this.workingDirName = workingDirName;
}

View File

@@ -113,7 +113,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
public MappingsProviderImpl(Project project) {
super(project);
mappingsDir = getExtension().getUserCache().toPath().resolve("mappings");
mappingsDir = getDirectories().getUserCache().toPath().resolve("mappings");
mappingsStepsDir = mappingsDir.resolve("steps");
}
@@ -214,7 +214,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
Path mappedVersionedDir = getMappedVersionedDir(removeSuffix);
tinyMappings = mappedVersionedDir.resolve("mappings.tiny").toFile();
unpickDefinitionsFile = mappedVersionedDir.resolve("definitions.unpick").toFile();
tinyMappingsJar = new File(getExtension().getUserCache(), removeSuffix + "-" + jarClassifier + ".jar");
tinyMappingsJar = new File(getDirectories().getUserCache(), removeSuffix + "-" + jarClassifier + ".jar");
tinyMappingsWithSrg = mappedVersionedDir.resolve("mappings-srg.tiny");
mixinTinyMappingsWithSrg = mappedVersionedDir.resolve("mappings-mixin-srg.tiny").toFile();
srgToNamedSrg = mappedVersionedDir.resolve("mappings-srg-named.srg").toFile();
@@ -277,7 +277,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
LoomGradleExtension extension = getExtension();
if (extension.accessWidener != null) {
if (extension.getAccessWidener() != null) {
extension.addJarProcessor(new AccessWidenerJarProcessor(getProject()));
}
@@ -545,7 +545,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
// Download and extract intermediary
String encodedMinecraftVersion = UrlEscapers.urlFragmentEscaper().escape(minecraftVersion);
String intermediaryArtifactUrl = getExtension().getIntermediaryUrl().apply(encodedMinecraftVersion);
String intermediaryArtifactUrl = getExtension().getIntermediaryUrl(encodedMinecraftVersion);
Path intermediaryJar = getMappingsVersionedDir().resolve("intermediary-v2.jar");
DownloadUtil.downloadIfChanged(new URL(intermediaryArtifactUrl), intermediaryJar.toFile(), getProject().getLogger());

View File

@@ -48,7 +48,7 @@ public class MinecraftLibraryProvider {
}
private void initFiles(Project project, MinecraftProviderImpl minecraftProvider) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
MINECRAFT_LIBS = new File(extension.getUserCache(), "libraries");
LoomGradleExtension extension = LoomGradleExtension.get(project);
MINECRAFT_LIBS = new File(extension.getFiles().getUserCache(), "libraries");
}
}

View File

@@ -352,9 +352,9 @@ public class MinecraftMappedProvider extends DependencyProvider {
public void initFiles(MinecraftProviderImpl minecraftProvider, MappingsProviderImpl mappingsProvider) {
this.minecraftProvider = minecraftProvider;
minecraftIntermediaryJar = new File(getExtension().getUserCache(), "minecraft-" + getJarVersionString("intermediary") + ".jar");
minecraftIntermediaryJar = new File(getDirectories().getUserCache(), "minecraft-" + getJarVersionString("intermediary") + ".jar");
minecraftSrgJar = !getExtension().isForge() ? null : new File(getExtension().getUserCache(), "minecraft-" + getJarVersionString("srg") + ".jar");
minecraftMappedJar = new File(getJarDirectory(getExtension().getUserCache(), "mapped"), "minecraft-" + getJarVersionString("mapped") + ".jar");
minecraftMappedJar = new File(getJarDirectory(getDirectories().getUserCache(), "mapped"), "minecraft-" + getJarVersionString("mapped") + ".jar");
inputJar = getExtension().isForge() ? mappingsProvider.patchedProvider.getMergedJar() : minecraftProvider.getMergedJar();
if (getExtension().isForge()) {
@@ -398,7 +398,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
}
public File getUnpickedJar() {
return new File(getJarDirectory(getExtension().getUserCache(), "mapped"), "minecraft-" + getJarVersionString("unpicked") + ".jar");
return new File(getJarDirectory(getDirectories().getUserCache(), "mapped"), "minecraft-" + getJarVersionString("unpicked") + ".jar");
}
@Override

View File

@@ -49,10 +49,10 @@ public class MinecraftNativesProvider {
public MinecraftNativesProvider(Project project) {
this.project = project;
extension = project.getExtensions().getByType(LoomGradleExtension.class);
extension = LoomGradleExtension.get(project);
nativesDir = extension.getNativesDirectory();
jarStore = extension.getNativesJarStore();
nativesDir = extension.getFiles().getNativesDirectory(extension.getMinecraftProvider());
jarStore = extension.getFiles().getNativesJarStore();
}
public static void provide(Project project) throws IOException {
@@ -60,7 +60,7 @@ public class MinecraftNativesProvider {
}
private void provide() throws IOException {
if (extension.hasCustomNatives()) {
if (extension.getFiles().hasCustomNatives()) {
if (!nativesDir.exists()) {
throw new RuntimeException("Could no find custom natives directory at " + nativesDir.getAbsolutePath());
}

View File

@@ -50,14 +50,14 @@ import net.fabricmc.loom.util.HashedDownloadUtil;
public class MinecraftAssetsProvider {
public static void provide(MinecraftProviderImpl minecraftProvider, Project project) throws IOException {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
boolean offline = project.getGradle().getStartParameter().isOffline();
MinecraftVersionMeta versionInfo = minecraftProvider.getVersionInfo();
MinecraftVersionMeta.AssetIndex assetIndex = versionInfo.assetIndex();
// get existing cache files
File assets = new File(extension.getUserCache(), "assets");
File assets = new File(extension.getFiles().getUserCache(), "assets");
if (!assets.exists()) {
assets.mkdirs();

View File

@@ -35,7 +35,7 @@ public final class DecompilerConfiguration {
}
public static void setup(Project project) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
extension.addDecompiler(new FabricFernFlowerDecompiler(project));
extension.addDecompiler(new FabricCFRDecompiler(project));
}

View File

@@ -0,0 +1,43 @@
/*
* 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 net.fabricmc.loom.configuration.providers.MinecraftProvider;
public interface LoomFiles {
File getUserCache();
File getRootProjectPersistentCache();
File getProjectPersistentCache();
File getProjectBuildCache();
File getRemappedModCache();
File getNativesJarStore();
boolean hasCustomNatives();
File getNativesDirectory(MinecraftProvider minecraftProvider);
File getDefaultLog4jConfigFile();
File getDevLauncherConfig();
File getUnpickLoggingConfigFile();
}

View File

@@ -0,0 +1,128 @@
/*
* 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 org.gradle.api.Project;
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
public final class LoomFilesImpl implements LoomFiles {
private final Project project;
private final File userCache;
private final File rootProjectPersistentCache;
private final File projectPersistentCache;
private final File projectBuildCache;
private final File remappedModCache;
private final File nativesJarStore;
public LoomFilesImpl(Project project) {
this.project = project;
this.userCache = createFile(project.getGradle().getGradleUserHomeDir(), "caches" + File.separator + "fabric-loom");
this.rootProjectPersistentCache = createFile(project.getRootProject().file(".gradle"), "loom-cache");
this.projectPersistentCache = createFile(project.file(".gradle"), "loom-cache");
this.projectBuildCache = createFile(project.getBuildDir(), "loom-cache");
this.remappedModCache = createFile(getRootProjectPersistentCache(), "remapped_mods");
this.nativesJarStore = createFile(getUserCache(), "natives/jars");
}
private File createFile(File parent, String child) {
File file = new File(parent, child);
if (!file.exists()) {
file.mkdirs();
}
return file;
}
@Override
public File getUserCache() {
return userCache;
}
@Override
public File getRootProjectPersistentCache() {
return rootProjectPersistentCache;
}
@Override
public File getProjectPersistentCache() {
return projectPersistentCache;
}
@Override
public File getProjectBuildCache() {
return projectBuildCache;
}
@Override
public File getRemappedModCache() {
return remappedModCache;
}
@Override
public File getNativesJarStore() {
return nativesJarStore;
}
@Override
public boolean hasCustomNatives() {
return project.getProperties().get("fabric.loom.natives.dir") != null;
}
@Override
public File getNativesDirectory(MinecraftProvider minecraftProvider) {
if (hasCustomNatives()) {
return new File((String) project.property("fabric.loom.natives.dir"));
}
File natives = new File(getUserCache(), "natives/" + minecraftProvider.minecraftVersion());
if (!natives.exists()) {
natives.mkdirs();
}
return natives;
}
@Override
public File getDefaultLog4jConfigFile() {
return new File(getProjectPersistentCache(), "log4j.xml");
}
@Override
public File getDevLauncherConfig() {
return new File(getProjectPersistentCache(), "launch.cfg");
}
@Override
public File getUnpickLoggingConfigFile() {
return new File(getProjectPersistentCache(), "unpick-logging.properties");
}
}

View File

@@ -0,0 +1,207 @@
/*
* 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.ArrayList;
import java.util.List;
import java.util.Objects;
import org.gradle.api.Action;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Project;
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;
import net.fabricmc.loom.configuration.processors.JarProcessor;
import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext;
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec;
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder;
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency;
/**
* This class implements the public extension api.
*/
public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionAPI {
protected final List<LoomDecompiler> decompilers = new ArrayList<>();
protected final List<JarProcessor> jarProcessors = new ArrayList<>();
protected final ConfigurableFileCollection log4jConfigs;
protected File accessWidener = null;
protected boolean shareCaches = false;
protected String refmapName = null;
protected boolean remapMod = true;
protected String customManifest;
private NamedDomainObjectContainer<RunConfigSettings> runConfigs;
protected LoomGradleExtensionApiImpl(Project project, LoomFiles directories) {
this.runConfigs = project.container(RunConfigSettings.class,
baseName -> new RunConfigSettings(project, baseName));
this.log4jConfigs = project.files(directories.getDefaultLog4jConfigFile());
}
@Override
public File getAccessWidener() {
return accessWidener;
}
@Override
public void setAccessWidener(Object file) {
Objects.requireNonNull(file, "Access widener file cannot be null");
this.accessWidener = getProject().file(file);
}
@Override
public void setShareCaches(boolean shareCaches) {
this.shareCaches = shareCaches;
}
@Override
public boolean isShareCaches() {
return shareCaches;
}
@Override
public List<LoomDecompiler> getDecompilers() {
return decompilers;
}
@Override
public void addDecompiler(LoomDecompiler decompiler) {
Objects.requireNonNull(decompiler, "Decompiler cannot be null");
decompilers.add(decompiler);
}
@Override
public List<JarProcessor> getJarProcessors() {
return jarProcessors;
}
@Override
public void addJarProcessor(JarProcessor processor) {
Objects.requireNonNull(processor, "Jar processor cannot be null");
jarProcessors.add(processor);
}
@Override
public Dependency layered(Action<LayeredMappingSpecBuilder> action) {
LayeredMappingSpecBuilder builder = new LayeredMappingSpecBuilder();
action.execute(builder);
LayeredMappingSpec builtSpec = builder.build();
return new LayeredMappingsDependency(new GradleMappingContext(getProject(), "layers_" + builtSpec.getVersion().replace("+", "_").replace(".", "_")), builtSpec, builtSpec.getVersion());
}
@Override
public String getRefmapName() {
if (refmapName == null || refmapName.isEmpty()) {
String defaultRefmapName = getProject().getConvention().getPlugin(BasePluginConvention.class).getArchivesBaseName() + "-refmap.json";
getProject().getLogger().info("Could not find refmap definition, will be using default name: " + defaultRefmapName);
refmapName = defaultRefmapName;
}
return refmapName;
}
@Override
public void setRefmapName(String refmapName) {
this.refmapName = refmapName;
}
@Override
public void setRemapMod(boolean remapMod) {
this.remapMod = remapMod;
}
@Override
public void runs(Action<NamedDomainObjectContainer<RunConfigSettings>> action) {
action.execute(runConfigs);
}
@Override
public NamedDomainObjectContainer<RunConfigSettings> getRunConfigs() {
return runConfigs;
}
@Override
public ConfigurableFileCollection getLog4jConfigs() {
return log4jConfigs;
}
@Override
public boolean isRemapMod() {
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");
this.customManifest = customManifest;
}
@Override
public String getCustomManifest() {
return customManifest;
}
protected abstract Project getProject();
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() {
super(null, null);
throw new RuntimeException();
}
@Override
protected Project getProject() {
throw new RuntimeException("Yeah... something is really wrong");
}
@Override
protected LoomFiles getFiles() {
throw new RuntimeException("Yeah... something is really wrong");
}
@Override
protected MixinApExtension getMixinApExtension() {
throw new RuntimeException("Yeah... something is really wrong");
}
}
}

View File

@@ -0,0 +1,170 @@
/*
* 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.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Supplier;
import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.mercury.Mercury;
import org.gradle.api.NamedDomainObjectProvider;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.ConfigurableFileCollection;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.InstallerData;
import net.fabricmc.loom.configuration.LoomDependencyManager;
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;
private final Set<File> mixinMappings = Collections.synchronizedSet(new HashSet<>());
private final MappingSet[] srcMappingCache = new MappingSet[2];
private final Mercury[] srcMercuryCache = new Mercury[2];
private final Map<String, NamedDomainObjectProvider<Configuration>> lazyConfigurations = new HashMap<>();
private LoomDependencyManager dependencyManager;
private JarProcessorManager jarProcessorManager;
private InstallerData installerData;
public LoomGradleExtensionImpl(Project project, LoomFiles files) {
super(project, files);
this.project = project;
this.mixinApExtension = new MixinApExtensionImpl(project);
this.loomFiles = files;
this.unmappedMods = project.files();
}
@Override
protected Project getProject() {
return project;
}
@Override
public LoomFiles getFiles() {
return loomFiles;
}
@Override
public synchronized File getNextMixinMappings() {
File mixinMapping = new File(getFiles().getProjectBuildCache(), "mixin-map-" + getMinecraftProvider().minecraftVersion() + "-" + getMappingsProvider().mappingsVersion + "." + mixinMappings.size() + ".tiny");
mixinMappings.add(mixinMapping);
return mixinMapping;
}
@Override
public Set<File> getAllMixinMappings() {
return mixinMappings;
}
@Override
public void setDependencyManager(LoomDependencyManager dependencyManager) {
this.dependencyManager = dependencyManager;
}
@Override
public LoomDependencyManager getDependencyManager() {
return Objects.requireNonNull(dependencyManager, "Cannot get LoomDependencyManager before it has been setup");
}
@Override
public void setJarProcessorManager(JarProcessorManager jarProcessorManager) {
this.jarProcessorManager = jarProcessorManager;
}
@Override
public JarProcessorManager getJarProcessorManager() {
return Objects.requireNonNull(jarProcessorManager, "Cannot get JarProcessorManager before it has been setup");
}
@Override
public MappingSet getOrCreateSrcMappingCache(int id, Supplier<MappingSet> factory) {
return srcMappingCache[id] != null ? srcMappingCache[id] : (srcMappingCache[id] = factory.get());
}
@Override
public Mercury getOrCreateSrcMercuryCache(int id, Supplier<Mercury> factory) {
return srcMercuryCache[id] != null ? srcMercuryCache[id] : (srcMercuryCache[id] = factory.get());
}
@Override
public ConfigurableFileCollection getUnmappedModCollection() {
return unmappedMods;
}
public void setInstallerData(InstallerData object) {
this.installerData = object;
}
@Override
public InstallerData getInstallerData() {
return installerData;
}
@Override
public boolean isRootProject() {
return project.getRootProject() == project;
}
@Override
public NamedDomainObjectProvider<Configuration> createLazyConfiguration(String name) {
NamedDomainObjectProvider<Configuration> provider = project.getConfigurations().register(name);
if (lazyConfigurations.containsKey(name)) {
throw new IllegalStateException("Duplicate configuration name" + name);
}
lazyConfigurations.put(name, provider);
return provider;
}
@Override
public NamedDomainObjectProvider<Configuration> getLazyConfigurationProvider(String name) {
NamedDomainObjectProvider<Configuration> provider = lazyConfigurations.get(name);
if (provider == null) {
throw new NullPointerException("Could not find provider with name: " + name);
}
return provider;
}
@Override
public MixinApExtension getMixinApExtension() {
return this.mixinApExtension;
}
}

View 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();
}

View File

@@ -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");
}
}
}

View File

@@ -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;
}
}

View File

@@ -37,6 +37,6 @@ public abstract class AbstractLoomTask extends DefaultTask {
@Internal
protected LoomGradleExtension getExtension() {
return getProject().getExtensions().getByType(LoomGradleExtension.class);
return LoomGradleExtension.get(getProject());
}
}

View File

@@ -83,10 +83,6 @@ public class GenerateSourcesTask extends AbstractLoomTask {
Files.copy(linemappedJarDestination, runtimeJar, StandardCopyOption.REPLACE_EXISTING);
Files.delete(linemappedJarDestination);
}
if (getExtension().isForge()) {
ForgeSourcesRemapper.addForgeSources(getProject(), sourcesDestination);
}
}
private void remapLineNumbers(Path oldCompiledJar, Path linemap, Path linemappedJarDestination) throws IOException {
@@ -114,7 +110,7 @@ public class GenerateSourcesTask extends AbstractLoomTask {
}
public static File getMappedJarFileWithSuffix(Project project, String suffix, boolean forgeJar) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(getProject());
MappingsProviderImpl mappingsProvider = extension.getMappingsProvider();
File mappedJar = forgeJar ? mappingsProvider.mappedProvider.getForgeMappedJar() : mappingsProvider.mappedProvider.getMappedJar();
String path = mappedJar.getAbsolutePath();

View File

@@ -89,7 +89,7 @@ public final class LoomTasks {
}
private static void registerRunTasks(TaskContainer tasks, Project project) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
Preconditions.checkArgument(extension.getRunConfigs().size() == 0, "Run configurations must not be registered before loom");
@@ -122,7 +122,7 @@ public final class LoomTasks {
}
private static void registerDecompileTasks(TaskContainer tasks, Project project) {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
project.afterEvaluate(p -> {
MappingsProviderImpl mappingsProvider = extension.getMappingsProvider();

View File

@@ -120,7 +120,7 @@ public class MigrateMappingsTask extends AbstractLoomTask {
try {
if (mappings.startsWith("net.minecraft:mappings:") || mappings.startsWith("net.mojang.minecraft:mappings:")) {
if (!mappings.endsWith(":" + project.getExtensions().getByType(LoomGradleExtension.class).getMinecraftProvider().minecraftVersion())) {
if (!mappings.endsWith(":" + LoomGradleExtension.get(project).getMinecraftProvider().minecraftVersion())) {
throw new UnsupportedOperationException("Migrating Mojang mappings is currently only supported for the specified minecraft version");
}

View File

@@ -137,7 +137,7 @@ public class RemapJarTask extends Jar {
jarRemapper = new JarRemapper();
}
scheduleRemap(singleRemap || getProject().getExtensions().getByType(LoomGradleExtension.class).isRootProject());
scheduleRemap(singleRemap || LoomGradleExtension.get(getProject()).isRootProject());
if (singleRemap) {
jarRemapper.remap(getProject());
@@ -212,7 +212,7 @@ public class RemapJarTask extends Jar {
public void scheduleRemap(boolean isMainRemapTask) throws Throwable {
Project project = getProject();
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(getProject());
Path input = this.getInput().getAsFile().get().toPath();
Path output = this.getArchivePath().toPath();
@@ -248,7 +248,7 @@ public class RemapJarTask extends Jar {
jarRemapper.scheduleRemap(input, output)
.supplyAccessWidener((remapData, remapper) -> {
if (getRemapAccessWidener().getOrElse(false) && extension.accessWidener != null) {
if (getRemapAccessWidener().getOrElse(false) && extension.getAccessWidener() != null) {
AccessWidenerJarProcessor accessWidenerJarProcessor = extension.getJarProcessorManager().getByType(AccessWidenerJarProcessor.class);
byte[] data;
@@ -271,7 +271,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!");
}

View File

@@ -31,7 +31,7 @@ import net.fabricmc.loom.configuration.ide.RunConfig;
public class RunClientTask extends AbstractRunTask {
public RunClientTask() {
super(project -> {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
return RunConfig.runConfig(project, extension.getRunConfigs().getByName("client"));
});
}

View File

@@ -31,7 +31,7 @@ import net.fabricmc.loom.configuration.ide.RunConfig;
public class RunServerTask extends AbstractRunTask {
public RunServerTask() {
super(project -> {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
return RunConfig.runConfig(project, extension.getRunConfigs().getByName("client"));
});
}

View File

@@ -36,6 +36,7 @@ import org.gradle.api.tasks.OutputFile;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.providers.LaunchProvider;
import net.fabricmc.loom.extension.LoomFiles;
import net.fabricmc.loom.util.Constants;
public class UnpickJarTask extends JavaExec {
@@ -60,15 +61,15 @@ public class UnpickJarTask extends JavaExec {
fileArg(getMinecraftDependencies());
writeUnpickLogConfig();
systemProperty("java.util.logging.config.file", getExtension().getUnpickLoggingConfigFile().getAbsolutePath());
systemProperty("java.util.logging.config.file", getDirectories().getUnpickLoggingConfigFile().getAbsolutePath());
super.exec();
}
private void writeUnpickLogConfig() {
try (InputStream is = LaunchProvider.class.getClassLoader().getResourceAsStream("unpick-logging.properties")) {
Files.deleteIfExists(getExtension().getUnpickLoggingConfigFile().toPath());
Files.copy(is, getExtension().getUnpickLoggingConfigFile().toPath());
Files.deleteIfExists(getDirectories().getUnpickLoggingConfigFile().toPath());
Files.copy(is, getDirectories().getUnpickLoggingConfigFile().toPath());
} catch (IOException e) {
throw new RuntimeException("Failed to copy unpick logging config", e);
}
@@ -121,6 +122,10 @@ public class UnpickJarTask extends JavaExec {
@Internal
protected LoomGradleExtension getExtension() {
return getProject().getExtensions().getByType(LoomGradleExtension.class);
return LoomGradleExtension.get(getProject());
}
private LoomFiles getDirectories() {
return getExtension().getFiles();
}
}

View File

@@ -37,6 +37,7 @@ public class Constants {
public static final String LIBRARIES_BASE = "https://libraries.minecraft.net/";
public static final String RESOURCES_BASE = "https://resources.download.minecraft.net/";
public static final String VERSION_MANIFESTS = "https://launchermeta.mojang.com/mc/game/version_manifest_v2.json";
public static final String EXPERIMENTAL_VERSIONS = "https://maven.fabricmc.net/net/minecraft/experimental_versions.json";
public static final String SYSTEM_ARCH = System.getProperty("os.arch").equals("64") ? "64" : "32";
public static final String TASK_CATEGORY = "loom";
@@ -127,14 +128,6 @@ public class Constants {
}
}
public static final class LaunchWrapper {
public static final String DEFAULT_FABRIC_CLIENT_TWEAKER = "net.fabricmc.loader.launch.FabricClientTweaker";
public static final String DEFAULT_FABRIC_SERVER_TWEAKER = "net.fabricmc.loader.launch.FabricServerTweaker";
private LaunchWrapper() {
}
}
public static final class Knot {
public static final String KNOT_CLIENT = "net.fabricmc.loader.launch.knot.KnotClient";
public static final String KNOT_SERVER = "net.fabricmc.loader.launch.knot.KnotServer";

View File

@@ -26,9 +26,11 @@ package net.fabricmc.loom.util;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPInputStream;
import com.google.common.io.Files;
import org.apache.commons.io.FileUtils;
@@ -110,7 +112,13 @@ public class DownloadUtil {
}
try { // Try download to the output
FileUtils.copyInputStreamToFile(connection.getInputStream(), to);
InputStream inputStream = connection.getInputStream();
if ("gzip".equals(connection.getContentEncoding())) {
inputStream = new GZIPInputStream(inputStream);
}
FileUtils.copyInputStreamToFile(inputStream, to);
} catch (IOException e) {
delete(to); // Probably isn't good if it fails to copy/save
throw e;

View File

@@ -27,9 +27,11 @@ package net.fabricmc.loom.util;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPInputStream;
import javax.annotation.Nullable;
@@ -106,7 +108,13 @@ public class HashedDownloadUtil {
}
try { // Try download to the output
FileUtils.copyInputStreamToFile(connection.getInputStream(), to);
InputStream inputStream = connection.getInputStream();
if ("gzip".equals(connection.getContentEncoding())) {
inputStream = new GZIPInputStream(inputStream);
}
FileUtils.copyInputStreamToFile(inputStream, to);
} catch (IOException e) {
delete(to); // Probably isn't good if it fails to copy/save
throw e;

View File

@@ -171,7 +171,7 @@ public class SourceRemapper {
return this.mercury;
}
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
LoomGradleExtension extension = LoomGradleExtension.get(project);
MappingsProviderImpl mappingsProvider = extension.getMappingsProvider();
String intermediary = extension.isForge() ? "srg" : "intermediary";

View File

@@ -0,0 +1,65 @@
/*
* 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.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait
import spock.lang.Specification
import spock.lang.Unroll
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class CustomManifestTest extends Specification implements ProjectTestTrait {
@Override
String name() {
"minimalBase"
}
@Override
def filesReady() {
buildGradle() << '''
loom {
customManifest = "https://maven.fabricmc.net/net/minecraft/1_18_experimental-snapshot-1.json"
}
dependencies {
minecraft "com.mojang:minecraft:1.18_experimental-snapshot-1"
mappings "net.fabricmc:yarn:1.18_experimental-snapshot-1+build.2:v2"
modImplementation "net.fabricmc:fabric-loader:0.11.6"
}
'''
}
@Unroll
def "customManifest (gradle #gradle)"() {
when:
def result = create("build", gradle)
then:
result.task(":build").outcome == SUCCESS
where:
gradle | _
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait
import spock.lang.Specification
import spock.lang.Unroll
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class ExperimentalVersionsTest extends Specification implements ProjectTestTrait {
@Override
String name() {
"minimalBase"
}
@Override
def filesReady() {
buildGradle() << '''
dependencies {
minecraft "com.mojang:minecraft:1.18_experimental-snapshot-1"
mappings "net.fabricmc:yarn:1.18_experimental-snapshot-1+build.2:v2"
modImplementation "net.fabricmc:fabric-loader:0.11.6"
}
'''
}
@Unroll
def "experimental versions (gradle #gradle)"() {
when:
def result = create("build", gradle)
then:
result.task(":build").outcome == SUCCESS
where:
gradle | _
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
}
}

View File

@@ -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 | _
}
}

View File

@@ -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 | _
}
}

View File

@@ -29,7 +29,7 @@ import org.gradle.testkit.runner.GradleRunner
trait ProjectTestTrait {
final static String DEFAULT_GRADLE = "7.0.1"
final static String PRE_RELEASE_GRADLE = "7.2-20210704221017+0000"
final static String PRE_RELEASE_GRADLE = "7.2-20210719222438+0000"
static File gradleHome = File.createTempDir()
File testProjectDir = File.createTempDir()
@@ -79,9 +79,17 @@ trait ProjectTestTrait {
gradleHome.deleteDir()
}
File buildGradle() {
return new File(testProjectDir, "build.gradle")
}
def filesReady() {
}
BuildResult create(String task, String gradleVersion = DEFAULT_GRADLE) {
System.setProperty("fabric.loom.test", "true")
copyInputFiles()
filesReady()
GradleRunner.create()
.withProjectDir(testProjectDir)

View File

@@ -0,0 +1,10 @@
// This is used by a range of tests that append to this file before running the gradle tasks.
// Can be used for tests that require minimal custom setup
plugins {
id 'fabric-loom'
id 'maven-publish'
}
archivesBaseName = "fabric-example-mod"
version = "1.0.0"
group = "com.example"

View 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.
}
}

View 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

View File

@@ -0,0 +1,10 @@
pluginManagement {
repositories {
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
gradlePluginPortal()
mavenLocal()
}
}

View File

@@ -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!");
}
}

View File

@@ -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

View File

@@ -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": "*"
}
}

View File

@@ -0,0 +1,14 @@
{
"required": true,
"minVersion": "0.8",
"package": "net.fabricmc.example.mixin",
"compatibilityLevel": "JAVA_16",
"mixins": [
],
"client": [
"ExampleMixinMain"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@@ -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!");
}
}

View File

@@ -0,0 +1,14 @@
{
"required": true,
"minVersion": "0.8",
"package": "net.fabricmc.example.mixin",
"compatibilityLevel": "JAVA_16",
"mixins": [
],
"client": [
"ExampleMixin0"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@@ -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!");
}
}

View File

@@ -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!");
}
}

View File

@@ -0,0 +1,14 @@
{
"required": true,
"minVersion": "0.8",
"package": "net.fabricmc.example.mixin",
"compatibilityLevel": "JAVA_16",
"mixins": [
],
"client": [
"ExampleMixin1_1"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@@ -0,0 +1,14 @@
{
"required": true,
"minVersion": "0.8",
"package": "net.fabricmc.example.mixin",
"compatibilityLevel": "JAVA_16",
"mixins": [
],
"client": [
"ExampleMixin1_2"
],
"injectors": {
"defaultRequire": 1
}
}

View 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.
}
}

View 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

View File

@@ -0,0 +1,10 @@
pluginManagement {
repositories {
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
gradlePluginPortal()
mavenLocal()
}
}

View File

@@ -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!");
}
}

View File

@@ -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

View File

@@ -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": "*"
}
}

View File

@@ -0,0 +1,14 @@
{
"required": true,
"minVersion": "0.8",
"package": "net.fabricmc.example.mixin",
"compatibilityLevel": "JAVA_16",
"mixins": [
],
"client": [
"ExampleMixin1"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@@ -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!");
}
}

View File

@@ -0,0 +1,14 @@
{
"required": true,
"minVersion": "0.8",
"package": "net.fabricmc.example.mixin",
"compatibilityLevel": "JAVA_16",
"mixins": [
],
"client": [
"ExampleMixin0"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@@ -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!");
}
}

View File

@@ -0,0 +1,14 @@
{
"required": true,
"minVersion": "0.8",
"package": "net.fabricmc.example.mixin",
"compatibilityLevel": "JAVA_16",
"mixins": [
],
"client": [
"ExampleMixin0"
],
"injectors": {
"defaultRequire": 1
}
}