Support ARM natives, rewrite native handling and misc cleanup. (#554)
* Rewrite natives handling, upgrade LWJGL on ARM machines. * Remove old natives override hack, should now always be done via gradle. * Use "idea" everywhere * Add server specific libraries onto their own classpath. Includes misc code cleanup. * Start on writing the excluded server libs. * Gradle deprecation fixes, and misc cleanup * Add support mod. * Make native support mod none transitive. * Update gradle.dev/0.11
parent
4ace257c37
commit
5a16440c1e
|
@ -13,7 +13,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/wrapper-validation-action@v1
|
||||||
- run: gradle build check -x test --stacktrace
|
- run: gradle build check -x test --stacktrace --warning-mode fail
|
||||||
|
|
||||||
# This job is used to feed the test matrix of next job to allow the tests to run in parallel
|
# This job is used to feed the test matrix of next job to allow the tests to run in parallel
|
||||||
prepare_test_matrix:
|
prepare_test_matrix:
|
||||||
|
@ -27,7 +27,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: gradle writeActionsTestMatrix --stacktrace
|
- run: gradle writeActionsTestMatrix --stacktrace --warning-mode fail
|
||||||
-
|
-
|
||||||
id: set-matrix
|
id: set-matrix
|
||||||
run: echo "::set-output name=matrix::$(cat build/test_matrix.json)"
|
run: echo "::set-output name=matrix::$(cat build/test_matrix.json)"
|
||||||
|
@ -51,7 +51,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: gradle test --tests ${{ matrix.test }} --stacktrace
|
- run: gradle test --tests ${{ matrix.test }} --stacktrace --warning-mode fail
|
||||||
env:
|
env:
|
||||||
TEST_WARNING_MODE: fail
|
TEST_WARNING_MODE: fail
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ jobs:
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
java-version: ${{ matrix.java }}
|
java-version: ${{ matrix.java }}
|
||||||
- run: ./gradlew test --tests ${{ matrix.test }} --stacktrace
|
- run: ./gradlew test --tests ${{ matrix.test }} --stacktrace --warning-mode fail
|
||||||
env:
|
env:
|
||||||
TEST_WARNING_MODE: fail
|
TEST_WARNING_MODE: fail
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
java-version: ${{ matrix.java }}
|
java-version: ${{ matrix.java }}
|
||||||
|
|
||||||
- run: ./gradlew test --tests *ReproducibleBuildTest --stacktrace
|
- run: ./gradlew test --tests *ReproducibleBuildTest --stacktrace --warning-mode fail
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
|
|
10
build.gradle
10
build.gradle
|
@ -37,6 +37,9 @@ repositories {
|
||||||
url = 'https://maven.fabricmc.net/'
|
url = 'https://maven.fabricmc.net/'
|
||||||
}
|
}
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
maven {
|
||||||
|
url = 'https://plugins.gradle.org/m2/'
|
||||||
|
}
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +95,9 @@ dependencies {
|
||||||
// source code remapping
|
// source code remapping
|
||||||
implementation ('net.fabricmc:mercury:0.2.4')
|
implementation ('net.fabricmc:mercury:0.2.4')
|
||||||
|
|
||||||
|
// IDEA support
|
||||||
|
implementation ('gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:1.1.1')
|
||||||
|
|
||||||
// Kapt integration
|
// Kapt integration
|
||||||
compileOnly('org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0')
|
compileOnly('org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0')
|
||||||
|
|
||||||
|
@ -162,8 +168,8 @@ jacoco {
|
||||||
jacocoTestReport {
|
jacocoTestReport {
|
||||||
dependsOn test
|
dependsOn test
|
||||||
reports {
|
reports {
|
||||||
xml.enabled false
|
xml.required = false
|
||||||
csv.enabled false
|
csv.required = false
|
||||||
html.destination file("${buildDir}/jacocoHtml")
|
html.destination file("${buildDir}/jacocoHtml")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.2-all.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
|
@ -31,6 +31,7 @@ import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.cadixdev.lorenz.MappingSet;
|
import org.cadixdev.lorenz.MappingSet;
|
||||||
import org.cadixdev.mercury.Mercury;
|
import org.cadixdev.mercury.Mercury;
|
||||||
|
import org.gradle.api.Action;
|
||||||
import org.gradle.api.NamedDomainObjectProvider;
|
import org.gradle.api.NamedDomainObjectProvider;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.artifacts.Configuration;
|
import org.gradle.api.artifacts.Configuration;
|
||||||
|
@ -54,7 +55,12 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
|
||||||
|
|
||||||
LoomFiles getFiles();
|
LoomFiles getFiles();
|
||||||
|
|
||||||
NamedDomainObjectProvider<Configuration> createLazyConfiguration(String name);
|
default NamedDomainObjectProvider<Configuration> createLazyConfiguration(String name) {
|
||||||
|
return createLazyConfiguration(name, config -> {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
NamedDomainObjectProvider<Configuration> createLazyConfiguration(String name, Action<? super Configuration> configurationAction);
|
||||||
|
|
||||||
NamedDomainObjectProvider<Configuration> getLazyConfigurationProvider(String name);
|
NamedDomainObjectProvider<Configuration> getLazyConfigurationProvider(String name);
|
||||||
|
|
||||||
|
@ -94,10 +100,6 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
|
||||||
|
|
||||||
boolean isRootProject();
|
boolean isRootProject();
|
||||||
|
|
||||||
default boolean ideSync() {
|
|
||||||
return Boolean.parseBoolean(System.getProperty("idea.sync.active", "false"));
|
|
||||||
}
|
|
||||||
|
|
||||||
default String getIntermediaryUrl(String minecraftVersion) {
|
default String getIntermediaryUrl(String minecraftVersion) {
|
||||||
return String.format(this.getIntermediaryUrl().get(), minecraftVersion);
|
return String.format(this.getIntermediaryUrl().get(), minecraftVersion);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import net.fabricmc.loom.configuration.CompileConfiguration;
|
||||||
import net.fabricmc.loom.configuration.FabricApiExtension;
|
import net.fabricmc.loom.configuration.FabricApiExtension;
|
||||||
import net.fabricmc.loom.configuration.MavenPublication;
|
import net.fabricmc.loom.configuration.MavenPublication;
|
||||||
import net.fabricmc.loom.configuration.ide.IdeConfiguration;
|
import net.fabricmc.loom.configuration.ide.IdeConfiguration;
|
||||||
|
import net.fabricmc.loom.configuration.ide.idea.IdeaConfiguration;
|
||||||
import net.fabricmc.loom.decompilers.DecompilerConfiguration;
|
import net.fabricmc.loom.decompilers.DecompilerConfiguration;
|
||||||
import net.fabricmc.loom.extension.LoomFiles;
|
import net.fabricmc.loom.extension.LoomFiles;
|
||||||
import net.fabricmc.loom.extension.LoomGradleExtensionImpl;
|
import net.fabricmc.loom.extension.LoomGradleExtensionImpl;
|
||||||
|
@ -84,5 +85,6 @@ public class LoomGradlePlugin implements BootstrappedPlugin {
|
||||||
MavenPublication.configure(project);
|
MavenPublication.configure(project);
|
||||||
LoomTasks.registerTasks(project);
|
LoomTasks.registerTasks(project);
|
||||||
DecompilerConfiguration.setup(project);
|
DecompilerConfiguration.setup(project);
|
||||||
|
IdeaConfiguration.setup(project);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,10 @@ package net.fabricmc.loom.api.mappings.layered.spec;
|
||||||
import groovy.lang.Closure;
|
import groovy.lang.Closure;
|
||||||
import groovy.lang.DelegatesTo;
|
import groovy.lang.DelegatesTo;
|
||||||
import org.gradle.api.Action;
|
import org.gradle.api.Action;
|
||||||
import org.gradle.util.ConfigureUtil;
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
import net.fabricmc.loom.util.ClosureAction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to configure a layered mapping spec.
|
* Used to configure a layered mapping spec.
|
||||||
*/
|
*/
|
||||||
|
@ -52,7 +53,7 @@ public interface LayeredMappingSpecBuilder {
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
default LayeredMappingSpecBuilder officialMojangMappings(@DelegatesTo(value = MojangMappingsSpecBuilder.class, strategy = Closure.DELEGATE_FIRST) Closure closure) {
|
default LayeredMappingSpecBuilder officialMojangMappings(@DelegatesTo(value = MojangMappingsSpecBuilder.class, strategy = Closure.DELEGATE_FIRST) Closure closure) {
|
||||||
return officialMojangMappings(mojangMappingsSpecBuilder -> ConfigureUtil.configure(closure, mojangMappingsSpecBuilder));
|
return officialMojangMappings(new ClosureAction<>(closure));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,7 +67,7 @@ public interface LayeredMappingSpecBuilder {
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
default LayeredMappingSpecBuilder parchment(Object object, @DelegatesTo(value = ParchmentMappingsSpecBuilder.class, strategy = Closure.DELEGATE_FIRST) Closure closure) {
|
default LayeredMappingSpecBuilder parchment(Object object, @DelegatesTo(value = ParchmentMappingsSpecBuilder.class, strategy = Closure.DELEGATE_FIRST) Closure closure) {
|
||||||
return parchment(object, parchmentMappingsSpecBuilder -> ConfigureUtil.configure(closure, parchmentMappingsSpecBuilder));
|
return parchment(object, new ClosureAction<>(closure));
|
||||||
}
|
}
|
||||||
|
|
||||||
LayeredMappingSpecBuilder parchment(Object object, Action<ParchmentMappingsSpecBuilder> action);
|
LayeredMappingSpecBuilder parchment(Object object, Action<ParchmentMappingsSpecBuilder> action);
|
||||||
|
|
|
@ -99,7 +99,7 @@ public class JarRemapper {
|
||||||
|
|
||||||
outputConsumer.addNonClassFiles(data.input);
|
outputConsumer.addNonClassFiles(data.input);
|
||||||
|
|
||||||
data.processAccessWidener(remapper.getRemapper());
|
data.processAccessWidener(remapper.getEnvironment().getRemapper());
|
||||||
remapper.apply(outputConsumer, data.tag);
|
remapper.apply(outputConsumer, data.tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.zip.ZipFile;
|
|
||||||
|
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
|
@ -58,6 +57,7 @@ import net.fabricmc.loom.configuration.processors.dependency.ModDependencyInfo;
|
||||||
import net.fabricmc.loom.configuration.processors.dependency.RemapData;
|
import net.fabricmc.loom.configuration.processors.dependency.RemapData;
|
||||||
import net.fabricmc.loom.util.Checksum;
|
import net.fabricmc.loom.util.Checksum;
|
||||||
import net.fabricmc.loom.util.Constants;
|
import net.fabricmc.loom.util.Constants;
|
||||||
|
import net.fabricmc.loom.util.ModUtils;
|
||||||
import net.fabricmc.loom.util.OperatingSystem;
|
import net.fabricmc.loom.util.OperatingSystem;
|
||||||
import net.fabricmc.loom.util.SourceRemapper;
|
import net.fabricmc.loom.util.SourceRemapper;
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ public class ModCompileRemapper {
|
||||||
String name = artifact.getModuleVersion().getId().getName();
|
String name = artifact.getModuleVersion().getId().getName();
|
||||||
String version = replaceIfNullOrEmpty(artifact.getModuleVersion().getId().getVersion(), () -> Checksum.truncatedSha256(artifact.getFile()));
|
String version = replaceIfNullOrEmpty(artifact.getModuleVersion().getId().getVersion(), () -> Checksum.truncatedSha256(artifact.getFile()));
|
||||||
|
|
||||||
if (!isFabricMod(logger, artifact.getFile(), artifact.getId())) {
|
if (!ModUtils.isMod(artifact.getFile())) {
|
||||||
addToRegularCompile(project, regularConfig, artifact);
|
addToRegularCompile(project, regularConfig, artifact);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ public class ModCompileRemapper {
|
||||||
|
|
||||||
// Create a mod dependency for each file in the file collection
|
// Create a mod dependency for each file in the file collection
|
||||||
for (File artifact : files) {
|
for (File artifact : files) {
|
||||||
if (!isFabricMod(logger, artifact, artifact.getName())) {
|
if (!ModUtils.isMod(artifact)) {
|
||||||
dependencies.add(regularConfig.getName(), project.files(artifact));
|
dependencies.add(regularConfig.getName(), project.files(artifact));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -161,22 +161,6 @@ public class ModCompileRemapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if an artifact is a fabric mod, according to the presence of a fabric.mod.json.
|
|
||||||
*/
|
|
||||||
private static boolean isFabricMod(Logger logger, File artifact, Object id) {
|
|
||||||
try (ZipFile zipFile = new ZipFile(artifact)) {
|
|
||||||
if (zipFile.getEntry("fabric.mod.json") != null) {
|
|
||||||
logger.info("Found Fabric mod in modCompile: {}", id);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
} catch (IOException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addToRegularCompile(Project project, Configuration regularCompile, ResolvedArtifact artifact) {
|
private static void addToRegularCompile(Project project, Configuration regularCompile, ResolvedArtifact artifact) {
|
||||||
project.getLogger().info(":providing " + artifact);
|
project.getLogger().info(":providing " + artifact);
|
||||||
DependencyHandler dependencies = project.getDependencies();
|
DependencyHandler dependencies = project.getDependencies();
|
||||||
|
|
|
@ -39,8 +39,9 @@ import org.gradle.api.artifacts.Configuration;
|
||||||
import org.gradle.api.artifacts.ConfigurationContainer;
|
import org.gradle.api.artifacts.ConfigurationContainer;
|
||||||
import org.gradle.api.tasks.SourceSet;
|
import org.gradle.api.tasks.SourceSet;
|
||||||
|
|
||||||
import net.fabricmc.loom.extension.MixinExtension;
|
|
||||||
import net.fabricmc.loom.LoomGradleExtension;
|
import net.fabricmc.loom.LoomGradleExtension;
|
||||||
|
import net.fabricmc.loom.configuration.ide.idea.IdeaUtils;
|
||||||
|
import net.fabricmc.loom.extension.MixinExtension;
|
||||||
import net.fabricmc.loom.util.Constants;
|
import net.fabricmc.loom.util.Constants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,9 +98,8 @@ public abstract class AnnotationProcessorInvoker<T extends Task> {
|
||||||
|
|
||||||
public void configureMixin() {
|
public void configureMixin() {
|
||||||
ConfigurationContainer configs = project.getConfigurations();
|
ConfigurationContainer configs = project.getConfigurations();
|
||||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
|
||||||
|
|
||||||
if (!extension.ideSync()) {
|
if (!IdeaUtils.isIdeaSync()) {
|
||||||
for (Configuration processorConfig : apConfigurations) {
|
for (Configuration processorConfig : apConfigurations) {
|
||||||
project.getLogger().info("Adding mixin to classpath of AP config: " + processorConfig.getName());
|
project.getLogger().info("Adding mixin to classpath of AP config: " + processorConfig.getName());
|
||||||
// Pass named MC classpath to mixin AP classpath
|
// Pass named MC classpath to mixin AP classpath
|
||||||
|
|
|
@ -58,7 +58,7 @@ public class JavaApInvoker extends AnnotationProcessorInvoker<JavaCompile> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected File getRefmapDestinationDir(JavaCompile task) {
|
protected File getRefmapDestinationDir(JavaCompile task) {
|
||||||
return task.getDestinationDir();
|
return task.getDestinationDirectory().getAsFile().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getAptConfigurationName(String sourceSet) {
|
private static String getAptConfigurationName(String sourceSet) {
|
||||||
|
|
|
@ -84,7 +84,7 @@ public class KaptApInvoker extends AnnotationProcessorInvoker<JavaCompile> {
|
||||||
try {
|
try {
|
||||||
String refmapName = Objects.requireNonNull(MixinExtension.getMixinInformationContainer(sourceSet)).refmapNameProvider().get();
|
String refmapName = Objects.requireNonNull(MixinExtension.getMixinInformationContainer(sourceSet)).refmapNameProvider().get();
|
||||||
Path src = Paths.get(getRefmapDestination(task, refmapName));
|
Path src = Paths.get(getRefmapDestination(task, refmapName));
|
||||||
Path dest = Paths.get(task.getDestinationDir().toString(), refmapName);
|
Path dest = Paths.get(task.getDestinationDirectory().get().getAsFile().toString(), refmapName);
|
||||||
|
|
||||||
// Possible that no mixin annotations exist
|
// Possible that no mixin annotations exist
|
||||||
if (Files.exists(src)) {
|
if (Files.exists(src)) {
|
||||||
|
|
|
@ -59,6 +59,6 @@ public class ScalaApInvoker extends AnnotationProcessorInvoker<ScalaCompile> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected File getRefmapDestinationDir(ScalaCompile task) {
|
protected File getRefmapDestinationDir(ScalaCompile task) {
|
||||||
return task.getDestinationDir();
|
return task.getDestinationDirectory().get().getAsFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ import net.fabricmc.loom.LoomGradleExtension;
|
||||||
import net.fabricmc.loom.LoomGradlePlugin;
|
import net.fabricmc.loom.LoomGradlePlugin;
|
||||||
import net.fabricmc.loom.task.RemapJarTask;
|
import net.fabricmc.loom.task.RemapJarTask;
|
||||||
import net.fabricmc.loom.util.Constants;
|
import net.fabricmc.loom.util.Constants;
|
||||||
|
import net.fabricmc.loom.util.ModUtils;
|
||||||
import net.fabricmc.loom.util.ZipUtils;
|
import net.fabricmc.loom.util.ZipUtils;
|
||||||
|
|
||||||
public final class NestedDependencyProvider implements NestedJarProvider {
|
public final class NestedDependencyProvider implements NestedJarProvider {
|
||||||
|
@ -158,7 +159,7 @@ public final class NestedDependencyProvider implements NestedJarProvider {
|
||||||
File file = metaFile.file;
|
File file = metaFile.file;
|
||||||
|
|
||||||
//A lib that doesnt have a mod.json, we turn it into a fake mod
|
//A lib that doesnt have a mod.json, we turn it into a fake mod
|
||||||
if (!ZipUtils.contains(file.toPath(), "fabric.mod.json")) {
|
if (!ModUtils.isMod(file)) {
|
||||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||||
File tempDir = new File(extension.getFiles().getUserCache(), "temp/modprocessing");
|
File tempDir = new File(extension.getFiles().getUserCache(), "temp/modprocessing");
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,11 @@ package net.fabricmc.loom.configuration;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import org.gradle.api.NamedDomainObjectProvider;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
|
import org.gradle.api.artifacts.Configuration;
|
||||||
import org.gradle.api.plugins.JavaPlugin;
|
import org.gradle.api.plugins.JavaPlugin;
|
||||||
import org.gradle.api.plugins.JavaPluginConvention;
|
import org.gradle.api.plugins.JavaPluginExtension;
|
||||||
import org.gradle.api.tasks.AbstractCopyTask;
|
import org.gradle.api.tasks.AbstractCopyTask;
|
||||||
import org.gradle.api.tasks.SourceSet;
|
import org.gradle.api.tasks.SourceSet;
|
||||||
import org.gradle.api.tasks.compile.JavaCompile;
|
import org.gradle.api.tasks.compile.JavaCompile;
|
||||||
|
@ -39,7 +41,6 @@ import net.fabricmc.loom.LoomGradleExtension;
|
||||||
import net.fabricmc.loom.build.mixin.JavaApInvoker;
|
import net.fabricmc.loom.build.mixin.JavaApInvoker;
|
||||||
import net.fabricmc.loom.build.mixin.KaptApInvoker;
|
import net.fabricmc.loom.build.mixin.KaptApInvoker;
|
||||||
import net.fabricmc.loom.build.mixin.ScalaApInvoker;
|
import net.fabricmc.loom.build.mixin.ScalaApInvoker;
|
||||||
import net.fabricmc.loom.configuration.ide.SetupIntelijRunConfigs;
|
|
||||||
import net.fabricmc.loom.configuration.providers.LaunchProvider;
|
import net.fabricmc.loom.configuration.providers.LaunchProvider;
|
||||||
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
|
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
|
||||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||||
|
@ -53,15 +54,20 @@ public final class CompileConfiguration {
|
||||||
public static void setupConfigurations(Project project) {
|
public static void setupConfigurations(Project project) {
|
||||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||||
|
|
||||||
extension.createLazyConfiguration(Constants.Configurations.MOD_COMPILE_CLASSPATH).configure(configuration -> configuration.setTransitive(true));
|
extension.createLazyConfiguration(Constants.Configurations.MOD_COMPILE_CLASSPATH, configuration -> configuration.setTransitive(true));
|
||||||
extension.createLazyConfiguration(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED).configure(configuration -> configuration.setTransitive(false));
|
extension.createLazyConfiguration(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED, 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_NAMED, configuration -> configuration.setTransitive(false)); // The launchers do not recurse dependencies
|
||||||
extension.createLazyConfiguration(Constants.Configurations.MINECRAFT_DEPENDENCIES).configure(configuration -> configuration.setTransitive(false));
|
NamedDomainObjectProvider<Configuration> serverDeps = extension.createLazyConfiguration(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES, configuration -> configuration.setTransitive(false));
|
||||||
extension.createLazyConfiguration(Constants.Configurations.LOADER_DEPENDENCIES).configure(configuration -> configuration.setTransitive(false));
|
extension.createLazyConfiguration(Constants.Configurations.MINECRAFT_DEPENDENCIES, configuration -> {
|
||||||
extension.createLazyConfiguration(Constants.Configurations.MINECRAFT).configure(configuration -> configuration.setTransitive(false));
|
configuration.extendsFrom(serverDeps.get());
|
||||||
extension.createLazyConfiguration(Constants.Configurations.INCLUDE).configure(configuration -> configuration.setTransitive(false)); // Dont get transitive deps
|
configuration.setTransitive(false);
|
||||||
|
});
|
||||||
|
extension.createLazyConfiguration(Constants.Configurations.MINECRAFT_NATIVES, configuration -> configuration.setTransitive(false));
|
||||||
|
extension.createLazyConfiguration(Constants.Configurations.LOADER_DEPENDENCIES, configuration -> configuration.setTransitive(false));
|
||||||
|
extension.createLazyConfiguration(Constants.Configurations.MINECRAFT, configuration -> configuration.setTransitive(false));
|
||||||
|
extension.createLazyConfiguration(Constants.Configurations.INCLUDE, configuration -> configuration.setTransitive(false)); // Dont get transitive deps
|
||||||
extension.createLazyConfiguration(Constants.Configurations.MAPPING_CONSTANTS);
|
extension.createLazyConfiguration(Constants.Configurations.MAPPING_CONSTANTS);
|
||||||
extension.createLazyConfiguration(Constants.Configurations.NAMED_ELEMENTS).configure(configuration -> {
|
extension.createLazyConfiguration(Constants.Configurations.NAMED_ELEMENTS, configuration -> {
|
||||||
configuration.setCanBeConsumed(true);
|
configuration.setCanBeConsumed(true);
|
||||||
configuration.setCanBeResolved(false);
|
configuration.setCanBeResolved(false);
|
||||||
configuration.extendsFrom(project.getConfigurations().getByName(JavaPlugin.API_CONFIGURATION_NAME));
|
configuration.extendsFrom(project.getConfigurations().getByName(JavaPlugin.API_CONFIGURATION_NAME));
|
||||||
|
@ -117,9 +123,9 @@ public final class CompileConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void configureCompile(Project p) {
|
public static void configureCompile(Project p) {
|
||||||
JavaPluginConvention javaModule = (JavaPluginConvention) p.getConvention().getPlugins().get("java");
|
final JavaPluginExtension javaPluginExtension = p.getExtensions().getByType(JavaPluginExtension.class);
|
||||||
|
|
||||||
SourceSet main = javaModule.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME);
|
SourceSet main = javaPluginExtension.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME);
|
||||||
|
|
||||||
Javadoc javadoc = (Javadoc) p.getTasks().getByName(JavaPlugin.JAVADOC_TASK_NAME);
|
Javadoc javadoc = (Javadoc) p.getTasks().getByName(JavaPlugin.JAVADOC_TASK_NAME);
|
||||||
javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath()));
|
javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath()));
|
||||||
|
@ -140,7 +146,6 @@ public final class CompileConfiguration {
|
||||||
project.getTasks().getByName("eclipse").finalizedBy(project.getTasks().getByName("genEclipseRuns"));
|
project.getTasks().getByName("eclipse").finalizedBy(project.getTasks().getByName("genEclipseRuns"));
|
||||||
project.getTasks().getByName("cleanEclipse").finalizedBy(project.getTasks().getByName("cleanEclipseRuns"));
|
project.getTasks().getByName("cleanEclipse").finalizedBy(project.getTasks().getByName("cleanEclipseRuns"));
|
||||||
|
|
||||||
SetupIntelijRunConfigs.setup(project);
|
|
||||||
extension.getRemapArchives().finalizeValue();
|
extension.getRemapArchives().finalizeValue();
|
||||||
|
|
||||||
// Enables the default mod remapper
|
// Enables the default mod remapper
|
||||||
|
|
|
@ -46,6 +46,7 @@ import net.fabricmc.loom.LoomGradlePlugin;
|
||||||
import net.fabricmc.loom.LoomRepositoryPlugin;
|
import net.fabricmc.loom.LoomRepositoryPlugin;
|
||||||
import net.fabricmc.loom.build.ModCompileRemapper;
|
import net.fabricmc.loom.build.ModCompileRemapper;
|
||||||
import net.fabricmc.loom.configuration.DependencyProvider.DependencyInfo;
|
import net.fabricmc.loom.configuration.DependencyProvider.DependencyInfo;
|
||||||
|
import net.fabricmc.loom.configuration.ide.idea.IdeaUtils;
|
||||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||||
import net.fabricmc.loom.util.Constants;
|
import net.fabricmc.loom.util.Constants;
|
||||||
import net.fabricmc.loom.util.SourceRemapper;
|
import net.fabricmc.loom.util.SourceRemapper;
|
||||||
|
@ -209,7 +210,7 @@ public class LoomDependencyManager {
|
||||||
loaderDepsConfig.getDependencies().add(modDep);
|
loaderDepsConfig.getDependencies().add(modDep);
|
||||||
|
|
||||||
// TODO: work around until https://github.com/FabricMC/Mixin/pull/60 and https://github.com/FabricMC/fabric-mixin-compile-extensions/issues/14 is fixed.
|
// TODO: work around until https://github.com/FabricMC/Mixin/pull/60 and https://github.com/FabricMC/fabric-mixin-compile-extensions/issues/14 is fixed.
|
||||||
if (!extension.ideSync() && extension.getMixin().getUseLegacyMixinAp().get()) {
|
if (!IdeaUtils.isIdeaSync() && extension.getMixin().getUseLegacyMixinAp().get()) {
|
||||||
apDepsConfig.getDependencies().add(modDep);
|
apDepsConfig.getDependencies().add(modDep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,7 @@ public class TransitiveAccessWidenerJarProcessor implements JarProcessor {
|
||||||
try {
|
try {
|
||||||
AccessWidenerRemapper remappingVisitor = new AccessWidenerRemapper(
|
AccessWidenerRemapper remappingVisitor = new AccessWidenerRemapper(
|
||||||
accessWidener,
|
accessWidener,
|
||||||
tinyRemapper.getRemapper(),
|
tinyRemapper.getEnvironment().getRemapper(),
|
||||||
MappingsNamespace.INTERMEDIARY.toString(),
|
MappingsNamespace.INTERMEDIARY.toString(),
|
||||||
MappingsNamespace.NAMED.toString()
|
MappingsNamespace.NAMED.toString()
|
||||||
);
|
);
|
||||||
|
|
|
@ -45,6 +45,7 @@ import org.w3c.dom.Node;
|
||||||
|
|
||||||
import net.fabricmc.loom.LoomGradleExtension;
|
import net.fabricmc.loom.LoomGradleExtension;
|
||||||
import net.fabricmc.loom.configuration.InstallerData;
|
import net.fabricmc.loom.configuration.InstallerData;
|
||||||
|
import net.fabricmc.loom.configuration.ide.idea.IdeaSyncTask;
|
||||||
|
|
||||||
public class RunConfig {
|
public class RunConfig {
|
||||||
public String configName;
|
public String configName;
|
||||||
|
@ -174,7 +175,7 @@ public class RunConfig {
|
||||||
public String fromDummy(String dummy, boolean relativeDir, Project project) throws IOException {
|
public String fromDummy(String dummy, boolean relativeDir, Project project) throws IOException {
|
||||||
String dummyConfig;
|
String dummyConfig;
|
||||||
|
|
||||||
try (InputStream input = SetupIntelijRunConfigs.class.getClassLoader().getResourceAsStream(dummy)) {
|
try (InputStream input = IdeaSyncTask.class.getClassLoader().getResourceAsStream(dummy)) {
|
||||||
dummyConfig = new String(input.readAllBytes(), StandardCharsets.UTF_8);
|
dummyConfig = new String(input.readAllBytes(), StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ import java.util.function.Function;
|
||||||
|
|
||||||
import org.gradle.api.Named;
|
import org.gradle.api.Named;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.plugins.JavaPluginConvention;
|
import org.gradle.api.plugins.JavaPluginExtension;
|
||||||
import org.gradle.api.tasks.SourceSet;
|
import org.gradle.api.tasks.SourceSet;
|
||||||
|
|
||||||
import net.fabricmc.loom.LoomGradleExtension;
|
import net.fabricmc.loom.LoomGradleExtension;
|
||||||
|
@ -229,10 +229,7 @@ public final class RunConfigSettings implements Named {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void source(String source) {
|
public void source(String source) {
|
||||||
setSource(proj -> {
|
setSource(proj -> project.getExtensions().getByType(JavaPluginExtension.class).getSourceSets().getByName(source));
|
||||||
JavaPluginConvention conv = proj.getConvention().getPlugin(JavaPluginConvention.class);
|
|
||||||
return conv.getSourceSets().getByName(source);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ideConfigGenerated(boolean ideConfigGenerated) {
|
public void ideConfigGenerated(boolean ideConfigGenerated) {
|
||||||
|
@ -243,7 +240,7 @@ public final class RunConfigSettings implements Named {
|
||||||
* Add the {@code -XstartOnFirstThread} JVM argument when on OSX.
|
* Add the {@code -XstartOnFirstThread} JVM argument when on OSX.
|
||||||
*/
|
*/
|
||||||
public void startFirstThread() {
|
public void startFirstThread() {
|
||||||
if (OperatingSystem.getOS().equalsIgnoreCase("osx")) {
|
if (OperatingSystem.CURRENT_OS.equals(OperatingSystem.MAC_OS)) {
|
||||||
vmArg("-XstartOnFirstThread");
|
vmArg("-XstartOnFirstThread");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,90 +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.ide;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
import org.gradle.api.Project;
|
|
||||||
|
|
||||||
import net.fabricmc.loom.LoomGradleExtension;
|
|
||||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftNativesProvider;
|
|
||||||
import net.fabricmc.loom.configuration.providers.minecraft.assets.MinecraftAssetsProvider;
|
|
||||||
|
|
||||||
public class SetupIntelijRunConfigs {
|
|
||||||
public static void setup(Project project) {
|
|
||||||
File projectDir = project.getRootProject().file(".idea");
|
|
||||||
|
|
||||||
if (!projectDir.exists()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
generate(project);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException("Failed to generate run configs", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void generate(Project project) throws IOException {
|
|
||||||
Project rootProject = project.getRootProject();
|
|
||||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
|
||||||
|
|
||||||
if (extension.ideSync()) {
|
|
||||||
//Ensures the assets are downloaded when idea is syncing a project
|
|
||||||
MinecraftAssetsProvider.provide(extension.getMinecraftProvider(), project);
|
|
||||||
MinecraftNativesProvider.provide(project);
|
|
||||||
}
|
|
||||||
|
|
||||||
String projectPath = project == rootProject ? "" : project.getPath().replace(':', '_');
|
|
||||||
|
|
||||||
File projectDir = rootProject.file(".idea");
|
|
||||||
File runConfigsDir = new File(projectDir, "runConfigurations");
|
|
||||||
|
|
||||||
if (!runConfigsDir.exists()) {
|
|
||||||
runConfigsDir.mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (RunConfigSettings settings : extension.getRunConfigs()) {
|
|
||||||
if (!settings.isIdeConfigGenerated()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
RunConfig config = RunConfig.runConfig(project, settings);
|
|
||||||
String name = config.configName.replaceAll("[^a-zA-Z0-9$_]", "_");
|
|
||||||
|
|
||||||
File runConfigs = new File(runConfigsDir, name + projectPath + ".xml");
|
|
||||||
String runConfigXml = config.fromDummy("idea_run_config_template.xml", true, project);
|
|
||||||
|
|
||||||
if (!runConfigs.exists()) {
|
|
||||||
FileUtils.writeStringToFile(runConfigs, runConfigXml, StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
|
|
||||||
settings.makeRunDir();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* 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.configuration.ide.idea;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.gradle.api.NamedDomainObjectContainer;
|
||||||
|
import org.gradle.api.Project;
|
||||||
|
import org.gradle.api.plugins.ExtensionAware;
|
||||||
|
import org.gradle.api.tasks.TaskProvider;
|
||||||
|
import org.gradle.plugins.ide.idea.model.IdeaModel;
|
||||||
|
import org.gradle.plugins.ide.idea.model.IdeaProject;
|
||||||
|
import org.jetbrains.gradle.ext.ActionDelegationConfig;
|
||||||
|
import org.jetbrains.gradle.ext.IdeaExtPlugin;
|
||||||
|
import org.jetbrains.gradle.ext.ProjectSettings;
|
||||||
|
import org.jetbrains.gradle.ext.RunConfiguration;
|
||||||
|
import org.jetbrains.gradle.ext.TaskTriggersConfig;
|
||||||
|
|
||||||
|
public class IdeaConfiguration {
|
||||||
|
public static void setup(Project project) {
|
||||||
|
TaskProvider<IdeaSyncTask> ideaSyncTask = project.getTasks().register("ideaSyncTask", IdeaSyncTask.class, ideaSyncTask1 -> {
|
||||||
|
ideaSyncTask1.dependsOn(project.getTasks().named("downloadAssets"));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!IdeaUtils.isIdeaSync()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
project.getPlugins().apply(IdeaExtPlugin.class);
|
||||||
|
project.getPlugins().withType(IdeaExtPlugin.class, ideaExtPlugin -> {
|
||||||
|
if (project != project.getRootProject()) {
|
||||||
|
// Also ensure it's applied to the root project.
|
||||||
|
project.getRootProject().getPlugins().apply(IdeaExtPlugin.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
final IdeaModel ideaModel = project.getRootProject().getExtensions().findByType(IdeaModel.class);
|
||||||
|
|
||||||
|
if (ideaModel == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final IdeaProject ideaProject = ideaModel.getProject();
|
||||||
|
|
||||||
|
if (ideaProject == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ProjectSettings settings = getExtension(ideaProject, ProjectSettings.class);
|
||||||
|
final ActionDelegationConfig delegateActions = getExtension(settings, ActionDelegationConfig.class);
|
||||||
|
final TaskTriggersConfig taskTriggers = getExtension(settings, TaskTriggersConfig.class);
|
||||||
|
final NamedDomainObjectContainer<RunConfiguration> runConfigurations = (NamedDomainObjectContainer<RunConfiguration>) ((ExtensionAware) settings).getExtensions().getByName("runConfigurations");
|
||||||
|
|
||||||
|
// Run the sync task on import
|
||||||
|
taskTriggers.afterSync(ideaSyncTask);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> T getExtension(Object extensionAware, Class<T> type) {
|
||||||
|
return Objects.requireNonNull(((ExtensionAware) extensionAware).getExtensions().getByType(type));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* 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.configuration.ide.idea;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.gradle.api.Project;
|
||||||
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
|
||||||
|
import net.fabricmc.loom.LoomGradleExtension;
|
||||||
|
import net.fabricmc.loom.configuration.ide.RunConfig;
|
||||||
|
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
|
||||||
|
import net.fabricmc.loom.configuration.providers.BundleMetadata;
|
||||||
|
import net.fabricmc.loom.task.AbstractLoomTask;
|
||||||
|
import net.fabricmc.loom.util.Constants;
|
||||||
|
|
||||||
|
public abstract class IdeaSyncTask extends AbstractLoomTask {
|
||||||
|
@Inject
|
||||||
|
public IdeaSyncTask() {
|
||||||
|
// Always re-run this task.
|
||||||
|
getOutputs().upToDateWhen(element -> false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
public void runTask() throws IOException {
|
||||||
|
File projectDir = getProject().getRootProject().file(".idea");
|
||||||
|
|
||||||
|
if (!projectDir.exists()) {
|
||||||
|
throw new RuntimeException("No .idea directory found");
|
||||||
|
}
|
||||||
|
|
||||||
|
generateRunConfigs();
|
||||||
|
}
|
||||||
|
|
||||||
|
// See: https://github.com/FabricMC/fabric-loom/pull/206#issuecomment-986054254 for the reason why XML's are still used to provide the run configs
|
||||||
|
private void generateRunConfigs() throws IOException {
|
||||||
|
Project rootProject = getProject().getRootProject();
|
||||||
|
LoomGradleExtension extension = LoomGradleExtension.get(getProject());
|
||||||
|
String projectPath = getProject() == rootProject ? "" : getProject().getPath().replace(':', '_');
|
||||||
|
File runConfigsDir = new File(rootProject.file(".idea"), "runConfigurations");
|
||||||
|
|
||||||
|
if (!runConfigsDir.exists()) {
|
||||||
|
runConfigsDir.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<String> excludedServerLibraries = getExcludedServerLibraries();
|
||||||
|
|
||||||
|
for (RunConfigSettings settings : extension.getRunConfigs()) {
|
||||||
|
if (!settings.isIdeConfigGenerated()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RunConfig config = RunConfig.runConfig(getProject(), settings);
|
||||||
|
String name = config.configName.replaceAll("[^a-zA-Z0-9$_]", "_");
|
||||||
|
|
||||||
|
File runConfigs = new File(runConfigsDir, name + projectPath + ".xml");
|
||||||
|
String runConfigXml = config.fromDummy("idea_run_config_template.xml", true, getProject());
|
||||||
|
|
||||||
|
if (!runConfigs.exists()) {
|
||||||
|
FileUtils.writeStringToFile(runConfigs, runConfigXml, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.makeRunDir();
|
||||||
|
|
||||||
|
if (settings.getEnvironment().equals("server") && !excludedServerLibraries.isEmpty()) {
|
||||||
|
try {
|
||||||
|
setClasspathModifications(runConfigs, excludedServerLibraries);
|
||||||
|
} catch (Exception e) {
|
||||||
|
getProject().getLogger().error("Failed to modify run configuration xml", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getExcludedServerLibraries() {
|
||||||
|
final BundleMetadata bundleMetadata = getExtension().getMinecraftProvider().getServerBundleMetadata();
|
||||||
|
|
||||||
|
if (bundleMetadata == null) {
|
||||||
|
// Legacy version
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final Set<File> allLibraries = getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).getFiles();
|
||||||
|
final Set<File> serverLibraries = getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES).getFiles();
|
||||||
|
final List<String> clientOnlyLibraries = new LinkedList<>();
|
||||||
|
|
||||||
|
for (File commonLibrary : allLibraries) {
|
||||||
|
if (!serverLibraries.contains(commonLibrary)) {
|
||||||
|
clientOnlyLibraries.add(commonLibrary.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientOnlyLibraries;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setClasspathModifications(File runConfig, List<String> exclusions) throws Exception {
|
||||||
|
// TODO modify the xml
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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.configuration.ide.idea;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class IdeaUtils {
|
||||||
|
public static boolean isIdeaSync() {
|
||||||
|
return Boolean.parseBoolean(System.getProperty("idea.sync.active", "false"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getIdeaVersion() {
|
||||||
|
return Objects.requireNonNull(System.getProperty("idea.version"), "Could not get idea version");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2021.3 or newer
|
||||||
|
public static boolean supportsCustomizableClasspath() {
|
||||||
|
final String[] split = getIdeaVersion().split("\\.");
|
||||||
|
final int major = Integer.parseInt(split[0]);
|
||||||
|
final int minor = Integer.parseInt(split[1]);
|
||||||
|
return major > 2021 || (major == 2021 && minor >= 3);
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,7 +30,7 @@ import java.io.IOException;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.plugins.JavaPluginConvention;
|
import org.gradle.api.plugins.JavaPluginExtension;
|
||||||
|
|
||||||
import net.fabricmc.loom.LoomGradlePlugin;
|
import net.fabricmc.loom.LoomGradlePlugin;
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ public class ModVersionParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private File locateModJsonFile() {
|
private File locateModJsonFile() {
|
||||||
return project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets()
|
return project.getExtensions().getByType(JavaPluginExtension.class).getSourceSets()
|
||||||
.getByName("main")
|
.getByName("main")
|
||||||
.getResources()
|
.getResources()
|
||||||
.matching(patternFilterable -> patternFilterable.include("fabric.mod.json"))
|
.matching(patternFilterable -> patternFilterable.include("fabric.mod.json"))
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* 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.configuration.providers;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import net.fabricmc.loom.util.FileSystemUtil;
|
||||||
|
|
||||||
|
public record BundleMetadata(List<Entry> libraries, List<Entry> versions, String mainClass) {
|
||||||
|
private static final String LIBRARIES_LIST_PATH = "META-INF/libraries.list";
|
||||||
|
private static final String VERSIONS_LIST_PATH = "META-INF/versions.list";
|
||||||
|
private static final String MAINCLASS_PATH = "META-INF/main-class";
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static BundleMetadata fromJar(Path jar) throws IOException {
|
||||||
|
final List<Entry> libraries;
|
||||||
|
final List<Entry> versions;
|
||||||
|
final String mainClass;
|
||||||
|
|
||||||
|
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(jar)) {
|
||||||
|
if (!Files.exists(fs.get().getPath(VERSIONS_LIST_PATH))) {
|
||||||
|
// Legacy jar
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
libraries = readEntries(fs.readString(LIBRARIES_LIST_PATH), "META-INF/libraries/");
|
||||||
|
versions = readEntries(fs.readString(VERSIONS_LIST_PATH), "META-INF/versions/");
|
||||||
|
mainClass = fs.readString(MAINCLASS_PATH).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BundleMetadata(libraries, versions, mainClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Entry> readEntries(String content, String pathPrefix) {
|
||||||
|
List<Entry> entries = new ArrayList<>();
|
||||||
|
|
||||||
|
for (String entry : content.split("\n")) {
|
||||||
|
if (entry.isBlank()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] split = entry.split("\t");
|
||||||
|
|
||||||
|
if (split.length != 3) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries.add(new Entry(split[0], split[1], pathPrefix + split[2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableList(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Entry(String sha1, String name, String path) {
|
||||||
|
public void unpackEntry(Path jar, Path dest) throws IOException {
|
||||||
|
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(jar);
|
||||||
|
InputStream is = Files.newInputStream(fs.get().getPath(path()))) {
|
||||||
|
Files.copy(is, dest, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,13 +54,15 @@ public class LaunchProvider extends DependencyProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws IOException {
|
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws IOException {
|
||||||
|
final String nativesPath = getExtension().getFiles().getNativesDirectory(getProject()).getAbsolutePath();
|
||||||
|
|
||||||
final LaunchConfig launchConfig = new LaunchConfig()
|
final LaunchConfig launchConfig = new LaunchConfig()
|
||||||
.property("fabric.development", "true")
|
.property("fabric.development", "true")
|
||||||
.property("fabric.remapClasspathFile", getRemapClasspathFile().getAbsolutePath())
|
.property("fabric.remapClasspathFile", getRemapClasspathFile().getAbsolutePath())
|
||||||
.property("log4j.configurationFile", getAllLog4JConfigFiles())
|
.property("log4j.configurationFile", getAllLog4JConfigFiles())
|
||||||
|
|
||||||
.property("client", "java.library.path", getExtension().getMinecraftProvider().nativesDir().getAbsolutePath())
|
.property("client", "java.library.path", nativesPath)
|
||||||
.property("client", "org.lwjgl.librarypath", getExtension().getMinecraftProvider().nativesDir().getAbsolutePath())
|
.property("client", "org.lwjgl.librarypath", nativesPath)
|
||||||
|
|
||||||
.argument("client", "--assetIndex")
|
.argument("client", "--assetIndex")
|
||||||
.argument("client", getExtension().getMinecraftProvider().getVersionInfo().assetIndex().fabricId(getExtension().getMinecraftProvider().minecraftVersion()))
|
.argument("client", getExtension().getMinecraftProvider().getVersionInfo().assetIndex().fabricId(getExtension().getMinecraftProvider().minecraftVersion()))
|
||||||
|
|
|
@ -31,10 +31,6 @@ import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
|
||||||
public interface MinecraftProvider {
|
public interface MinecraftProvider {
|
||||||
File workingDir();
|
File workingDir();
|
||||||
|
|
||||||
boolean hasCustomNatives();
|
|
||||||
|
|
||||||
File nativesDir();
|
|
||||||
|
|
||||||
File dir(String path);
|
File dir(String path);
|
||||||
|
|
||||||
File file(String path);
|
File file(String path);
|
||||||
|
|
|
@ -27,20 +27,16 @@ package net.fabricmc.loom.configuration.providers;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipFile;
|
|
||||||
|
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import org.gradle.api.GradleException;
|
import org.gradle.api.GradleException;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.logging.Logger;
|
import org.gradle.api.logging.Logger;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import net.fabricmc.loom.LoomGradlePlugin;
|
import net.fabricmc.loom.LoomGradlePlugin;
|
||||||
import net.fabricmc.loom.configuration.DependencyProvider;
|
import net.fabricmc.loom.configuration.DependencyProvider;
|
||||||
|
@ -48,9 +44,9 @@ import net.fabricmc.loom.configuration.providers.minecraft.ManifestVersion;
|
||||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftLibraryProvider;
|
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftLibraryProvider;
|
||||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
|
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
|
||||||
import net.fabricmc.loom.util.Constants;
|
import net.fabricmc.loom.util.Constants;
|
||||||
import net.fabricmc.loom.util.MirrorUtil;
|
|
||||||
import net.fabricmc.loom.util.DownloadUtil;
|
import net.fabricmc.loom.util.DownloadUtil;
|
||||||
import net.fabricmc.loom.util.HashedDownloadUtil;
|
import net.fabricmc.loom.util.HashedDownloadUtil;
|
||||||
|
import net.fabricmc.loom.util.MirrorUtil;
|
||||||
import net.fabricmc.stitch.merge.JarMerger;
|
import net.fabricmc.stitch.merge.JarMerger;
|
||||||
|
|
||||||
public class MinecraftProviderImpl extends DependencyProvider implements MinecraftProvider {
|
public class MinecraftProviderImpl extends DependencyProvider implements MinecraftProvider {
|
||||||
|
@ -66,6 +62,8 @@ public class MinecraftProviderImpl extends DependencyProvider implements Minecra
|
||||||
private File minecraftServerJar;
|
private File minecraftServerJar;
|
||||||
// The extracted server jar from the boostrap, only exists in >=21w39a
|
// The extracted server jar from the boostrap, only exists in >=21w39a
|
||||||
private File minecraftExtractedServerJar;
|
private File minecraftExtractedServerJar;
|
||||||
|
@Nullable
|
||||||
|
private BundleMetadata serverBundleMetadata;
|
||||||
private File minecraftMergedJar;
|
private File minecraftMergedJar;
|
||||||
private File versionManifestJson;
|
private File versionManifestJson;
|
||||||
private File experimentalVersionsJson;
|
private File experimentalVersionsJson;
|
||||||
|
@ -101,6 +99,8 @@ public class MinecraftProviderImpl extends DependencyProvider implements Minecra
|
||||||
downloadJars(getProject().getLogger());
|
downloadJars(getProject().getLogger());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serverBundleMetadata = BundleMetadata.fromJar(minecraftServerJar.toPath());
|
||||||
|
|
||||||
libraryProvider = new MinecraftLibraryProvider();
|
libraryProvider = new MinecraftLibraryProvider();
|
||||||
libraryProvider.provide(this, getProject());
|
libraryProvider.provide(this, getProject());
|
||||||
|
|
||||||
|
@ -257,61 +257,22 @@ public class MinecraftProviderImpl extends DependencyProvider implements Minecra
|
||||||
private void mergeJars(Logger logger) throws IOException {
|
private void mergeJars(Logger logger) throws IOException {
|
||||||
logger.info(":merging jars");
|
logger.info(":merging jars");
|
||||||
|
|
||||||
try (JarMerger jarMerger = new JarMerger(minecraftClientJar, getServerJarToMerge(logger), minecraftMergedJar)) {
|
File jarToMerge = minecraftServerJar;
|
||||||
jarMerger.enableSyntheticParamsOffset();
|
|
||||||
jarMerger.merge();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private File getServerJarToMerge(Logger logger) throws IOException {
|
|
||||||
try (ZipFile zipFile = new ZipFile(minecraftServerJar)) {
|
|
||||||
ZipEntry versionsListEntry = zipFile.getEntry("META-INF/versions.list");
|
|
||||||
|
|
||||||
if (versionsListEntry == null) {
|
|
||||||
// Legacy pre 21w38a jar
|
|
||||||
return minecraftServerJar;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (serverBundleMetadata != null) {
|
||||||
logger.info(":Extracting server jar from bootstrap");
|
logger.info(":Extracting server jar from bootstrap");
|
||||||
|
|
||||||
String versionsList;
|
if (serverBundleMetadata.versions().size() != 1) {
|
||||||
|
throw new UnsupportedOperationException("Expected only 1 version in META-INF/versions.list, but got %d".formatted(serverBundleMetadata.versions().size()));
|
||||||
try (InputStream is = zipFile.getInputStream(versionsListEntry)) {
|
|
||||||
versionsList = new String(is.readAllBytes(), StandardCharsets.UTF_8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String jarPath = null;
|
serverBundleMetadata.versions().get(0).unpackEntry(minecraftServerJar.toPath(), minecraftExtractedServerJar.toPath());
|
||||||
String[] versions = versionsList.split("\n");
|
jarToMerge = minecraftExtractedServerJar;
|
||||||
|
}
|
||||||
|
|
||||||
if (versions.length != 1) {
|
try (JarMerger jarMerger = new JarMerger(minecraftClientJar, jarToMerge, minecraftMergedJar)) {
|
||||||
throw new UnsupportedOperationException("Expected only 1 version in META-INF/versions.list, but got %d".formatted(versions.length));
|
jarMerger.enableSyntheticParamsOffset();
|
||||||
}
|
jarMerger.merge();
|
||||||
|
|
||||||
for (String version : versions) {
|
|
||||||
if (version.isBlank()) continue;
|
|
||||||
|
|
||||||
String[] split = version.split("\t");
|
|
||||||
|
|
||||||
if (split.length != 3) continue;
|
|
||||||
|
|
||||||
final String hash = split[0];
|
|
||||||
final String id = split[1];
|
|
||||||
final String path = split[2];
|
|
||||||
|
|
||||||
// Take the first (only) version we find.
|
|
||||||
jarPath = path;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Objects.requireNonNull(jarPath, "Could not find minecraft server jar for " + minecraftVersion());
|
|
||||||
ZipEntry serverJarEntry = zipFile.getEntry("META-INF/versions/" + jarPath);
|
|
||||||
Objects.requireNonNull(serverJarEntry, "Could not find server jar in boostrap@ " + jarPath);
|
|
||||||
|
|
||||||
try (InputStream is = zipFile.getInputStream(serverJarEntry)) {
|
|
||||||
java.nio.file.Files.copy(is, minecraftExtractedServerJar.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
}
|
|
||||||
|
|
||||||
return minecraftExtractedServerJar;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,20 +285,6 @@ public class MinecraftProviderImpl extends DependencyProvider implements Minecra
|
||||||
return workingDir;
|
return workingDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasCustomNatives() {
|
|
||||||
return getProject().getProperties().get("fabric.loom.natives.dir") != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public File nativesDir() {
|
|
||||||
if (hasCustomNatives()) {
|
|
||||||
return new File((String) getProject().property("fabric.loom.natives.dir"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return dir("natives");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File dir(String path) {
|
public File dir(String path) {
|
||||||
File dir = file(path);
|
File dir = file(path);
|
||||||
|
@ -368,4 +315,9 @@ public class MinecraftProviderImpl extends DependencyProvider implements Minecra
|
||||||
public String getTargetConfig() {
|
public String getTargetConfig() {
|
||||||
return Constants.Configurations.MINECRAFT;
|
return Constants.Configurations.MINECRAFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public BundleMetadata getServerBundleMetadata() {
|
||||||
|
return serverBundleMetadata;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* 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.configuration.providers.minecraft;
|
||||||
|
|
||||||
|
import static net.fabricmc.loom.util.OperatingSystem.LINUX;
|
||||||
|
import static net.fabricmc.loom.util.OperatingSystem.MAC_OS;
|
||||||
|
import static net.fabricmc.loom.util.OperatingSystem.WINDOWS;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.gradle.api.Project;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import net.fabricmc.loom.util.Architecture;
|
||||||
|
import net.fabricmc.loom.util.OperatingSystem;
|
||||||
|
|
||||||
|
public class LWJGLVersionOverride {
|
||||||
|
public static final String LWJGL_VERSION = "3.3.0";
|
||||||
|
@Nullable
|
||||||
|
public static final String NATIVE_CLASSIFIER = getNativesClassifier();
|
||||||
|
|
||||||
|
public static final List<String> DEPENDENCIES = List.of(
|
||||||
|
"org.lwjgl:lwjgl:" + LWJGL_VERSION,
|
||||||
|
"org.lwjgl:lwjgl-glfw:" + LWJGL_VERSION,
|
||||||
|
"org.lwjgl:lwjgl-jemalloc:" + LWJGL_VERSION,
|
||||||
|
"org.lwjgl:lwjgl-openal:" + LWJGL_VERSION,
|
||||||
|
"org.lwjgl:lwjgl-opengl:" + LWJGL_VERSION,
|
||||||
|
"org.lwjgl:lwjgl-stb:" + LWJGL_VERSION,
|
||||||
|
"org.lwjgl:lwjgl-tinyfd:" + LWJGL_VERSION
|
||||||
|
);
|
||||||
|
public static final List<String> NATIVES = DEPENDENCIES.stream().map(s -> s + ":" + NATIVE_CLASSIFIER).toList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update lwjgl by default when running on arm and a supported configuration.
|
||||||
|
*/
|
||||||
|
public static boolean overrideByDefault() {
|
||||||
|
return NATIVE_CLASSIFIER != null && Architecture.CURRENT.isArm();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean forceOverride(Project project) {
|
||||||
|
return project.getProperties().get("fabric.loom.override-lwjgl") != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static String getNativesClassifier() {
|
||||||
|
return switch (OperatingSystem.CURRENT_OS) {
|
||||||
|
case WINDOWS -> getWindowsClassifier();
|
||||||
|
case MAC_OS -> getMacOSClassifier();
|
||||||
|
case LINUX -> getLinuxClassifier();
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getWindowsClassifier() {
|
||||||
|
if (Architecture.CURRENT.is64Bit()) {
|
||||||
|
if (Architecture.CURRENT.isArm()) {
|
||||||
|
// Arm 64 bit
|
||||||
|
return "natives-windows-arm64";
|
||||||
|
}
|
||||||
|
|
||||||
|
// None arm 64bit
|
||||||
|
return "natives-windows";
|
||||||
|
}
|
||||||
|
|
||||||
|
// All 32bit, including arm
|
||||||
|
return "natives-windows-x86";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getMacOSClassifier() {
|
||||||
|
if (Architecture.CURRENT.isArm()) {
|
||||||
|
// Apple silicone arm
|
||||||
|
return "natives-macos-arm64";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intel 64bit.
|
||||||
|
return "natives-macos";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getLinuxClassifier() {
|
||||||
|
if (Architecture.CURRENT.isArm()) {
|
||||||
|
return Architecture.CURRENT.is64Bit() ? "natives-linux-arm64" : "natives-linux-arm32";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "natives-linux";
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,31 +24,77 @@
|
||||||
|
|
||||||
package net.fabricmc.loom.configuration.providers.minecraft;
|
package net.fabricmc.loom.configuration.providers.minecraft;
|
||||||
|
|
||||||
import java.io.File;
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
|
import org.gradle.api.artifacts.ExternalModuleDependency;
|
||||||
|
|
||||||
import net.fabricmc.loom.LoomGradleExtension;
|
import net.fabricmc.loom.configuration.providers.BundleMetadata;
|
||||||
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
|
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
|
||||||
import net.fabricmc.loom.util.Constants;
|
import net.fabricmc.loom.util.Constants;
|
||||||
|
|
||||||
public class MinecraftLibraryProvider {
|
public class MinecraftLibraryProvider {
|
||||||
public File MINECRAFT_LIBS;
|
private static final Pattern NATIVES_PATTERN = Pattern.compile("^(?<group>.*)/(.*?)/(?<version>.*)/((?<name>.*?)-([0-9].*?)-)(?<classifier>.*).jar$");
|
||||||
|
|
||||||
public void provide(MinecraftProviderImpl minecraftProvider, Project project) {
|
public void provide(MinecraftProviderImpl minecraftProvider, Project project) {
|
||||||
MinecraftVersionMeta versionInfo = minecraftProvider.getVersionInfo();
|
MinecraftVersionMeta versionInfo = minecraftProvider.getVersionInfo();
|
||||||
|
BundleMetadata serverBundleMetadata = minecraftProvider.getServerBundleMetadata();
|
||||||
|
|
||||||
initFiles(project, minecraftProvider);
|
final boolean overrideLWJGL = LWJGLVersionOverride.overrideByDefault() || LWJGLVersionOverride.forceOverride(project) || Boolean.getBoolean("loom.test.lwjgloverride");
|
||||||
|
|
||||||
|
if (overrideLWJGL) {
|
||||||
|
project.getLogger().warn("Loom is upgrading Minecraft's LWJGL version to {}", LWJGLVersionOverride.LWJGL_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
for (MinecraftVersionMeta.Library library : versionInfo.libraries()) {
|
for (MinecraftVersionMeta.Library library : versionInfo.libraries()) {
|
||||||
if (library.isValidForOS() && !library.hasNatives() && library.artifact() != null) {
|
if (overrideLWJGL && library.name().startsWith("org.lwjgl")) {
|
||||||
project.getDependencies().add(Constants.Configurations.MINECRAFT_DEPENDENCIES, project.getDependencies().module(library.name()));
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (library.isValidForOS() && !library.hasNatives() && library.artifact() != null) {
|
||||||
|
if (serverBundleMetadata != null && isLibraryInBundle(serverBundleMetadata, library)) {
|
||||||
|
project.getDependencies().add(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES, library.name());
|
||||||
|
} else {
|
||||||
|
// Client only library, or legacy version
|
||||||
|
project.getDependencies().add(Constants.Configurations.MINECRAFT_DEPENDENCIES, library.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (library.hasNativesForOS()) {
|
||||||
|
MinecraftVersionMeta.Download nativeDownload = library.classifierForOS();
|
||||||
|
|
||||||
|
Matcher matcher = NATIVES_PATTERN.matcher(nativeDownload.path());
|
||||||
|
|
||||||
|
if (!matcher.find()) {
|
||||||
|
project.getLogger().warn("Failed to match regex for natives path : " + nativeDownload.path());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String group = matcher.group("group").replace("/", ".");
|
||||||
|
final String name = matcher.group("name");
|
||||||
|
final String version = matcher.group("version");
|
||||||
|
final String classifier = matcher.group("classifier");
|
||||||
|
|
||||||
|
final String dependencyNotation = "%s:%s:%s:%s".formatted(group, name, version, classifier);
|
||||||
|
|
||||||
|
project.getLogger().debug("Add native dependency '{}'", dependencyNotation);
|
||||||
|
project.getDependencies().add(Constants.Configurations.MINECRAFT_NATIVES, dependencyNotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overrideLWJGL) {
|
||||||
|
LWJGLVersionOverride.DEPENDENCIES.forEach(s -> project.getDependencies().add(Constants.Configurations.MINECRAFT_DEPENDENCIES, s));
|
||||||
|
LWJGLVersionOverride.NATIVES.forEach(s -> project.getDependencies().add(Constants.Configurations.MINECRAFT_NATIVES, s));
|
||||||
|
|
||||||
|
// Add the native support mod that fixes a handful of issues related to the LWJGL update at runtime.
|
||||||
|
ExternalModuleDependency dependency = (ExternalModuleDependency) project.getDependencies().create(Constants.Dependencies.NATIVE_SUPPORT + Constants.Dependencies.Versions.NATIVE_SUPPORT_VERSION);
|
||||||
|
dependency.setTransitive(false);
|
||||||
|
project.getDependencies().add("modLocalRuntime", dependency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initFiles(Project project, MinecraftProviderImpl minecraftProvider) {
|
private static boolean isLibraryInBundle(BundleMetadata bundleMetadata, MinecraftVersionMeta.Library library) {
|
||||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
return bundleMetadata.libraries().stream().anyMatch(entry -> entry.name().equals(library.name()));
|
||||||
MINECRAFT_LIBS = new File(extension.getFiles().getUserCache(), "libraries");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
|
||||||
// Remap the sig fixes from intermediary to the target namespace
|
// Remap the sig fixes from intermediary to the target namespace
|
||||||
final Map<String, String> remapped = new HashMap<>();
|
final Map<String, String> remapped = new HashMap<>();
|
||||||
final TinyRemapper sigTinyRemapper = TinyRemapperHelper.getTinyRemapper(getProject(), MappingsNamespace.INTERMEDIARY.toString(), toM);
|
final TinyRemapper sigTinyRemapper = TinyRemapperHelper.getTinyRemapper(getProject(), MappingsNamespace.INTERMEDIARY.toString(), toM);
|
||||||
final Remapper sigAsmRemapper = sigTinyRemapper.getRemapper();
|
final Remapper sigAsmRemapper = sigTinyRemapper.getEnvironment().getRemapper();
|
||||||
|
|
||||||
// Remap the class names and the signatures using a new tiny remapper instance.
|
// Remap the class names and the signatures using a new tiny remapper instance.
|
||||||
for (Map.Entry<String, String> entry : mappingsProvider.getSignatureFixes().entrySet()) {
|
for (Map.Entry<String, String> entry : mappingsProvider.getSignatureFixes().entrySet()) {
|
||||||
|
|
|
@ -1,150 +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.providers.minecraft;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
import org.gradle.api.GradleException;
|
|
||||||
import org.gradle.api.Project;
|
|
||||||
|
|
||||||
import net.fabricmc.loom.LoomGradleExtension;
|
|
||||||
import net.fabricmc.loom.LoomGradlePlugin;
|
|
||||||
import net.fabricmc.loom.util.HashedDownloadUtil;
|
|
||||||
import net.fabricmc.loom.util.MirrorUtil;
|
|
||||||
import net.fabricmc.loom.util.ZipUtils;
|
|
||||||
|
|
||||||
public class MinecraftNativesProvider {
|
|
||||||
private final Project project;
|
|
||||||
private final LoomGradleExtension extension;
|
|
||||||
private final File nativesDir;
|
|
||||||
private final File jarStore;
|
|
||||||
|
|
||||||
public MinecraftNativesProvider(Project project) {
|
|
||||||
this.project = project;
|
|
||||||
extension = LoomGradleExtension.get(project);
|
|
||||||
|
|
||||||
nativesDir = extension.getMinecraftProvider().nativesDir();
|
|
||||||
jarStore = extension.getFiles().getNativesJarStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void provide(Project project) throws IOException {
|
|
||||||
new MinecraftNativesProvider(project).provide();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void provide() throws IOException {
|
|
||||||
if (extension.getMinecraftProvider().hasCustomNatives()) {
|
|
||||||
if (!nativesDir.exists()) {
|
|
||||||
throw new RuntimeException("Could no find custom natives directory at " + nativesDir.getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!LoomGradlePlugin.refreshDeps && !requiresExtract()) {
|
|
||||||
project.getLogger().info("Natives do no need extracting, skipping");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
extractNatives();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void extractNatives() throws IOException {
|
|
||||||
boolean offline = project.getGradle().getStartParameter().isOffline();
|
|
||||||
|
|
||||||
if (nativesDir.exists()) {
|
|
||||||
try {
|
|
||||||
FileUtils.deleteDirectory(nativesDir);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new IOException("Failed to delete the natives directory, is the game running?", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nativesDir.mkdirs();
|
|
||||||
|
|
||||||
for (MinecraftVersionMeta.Download library : getNatives()) {
|
|
||||||
File libJarFile = library.relativeFile(jarStore);
|
|
||||||
|
|
||||||
if (!offline) {
|
|
||||||
HashedDownloadUtil.downloadIfInvalid(new URL(MirrorUtil.getLibrariesBase(project) + library.path()), libJarFile, library.sha1(), project.getLogger(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!libJarFile.exists()) {
|
|
||||||
throw new GradleException("Native jar not found at " + libJarFile.getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
ZipUtils.unpackAll(libJarFile.toPath(), nativesDir.toPath());
|
|
||||||
|
|
||||||
// Store a file containing the hash of the extracted natives, used on subsequent runs to skip extracting all the natives if they haven't changed
|
|
||||||
File libSha1File = new File(nativesDir, libJarFile.getName() + ".sha1");
|
|
||||||
FileUtils.writeStringToFile(libSha1File, library.sha1(), StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean requiresExtract() {
|
|
||||||
List<MinecraftVersionMeta.Download> natives = getNatives();
|
|
||||||
|
|
||||||
if (natives.isEmpty()) {
|
|
||||||
throw new IllegalStateException("No natives found for the current system");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (MinecraftVersionMeta.Download library : natives) {
|
|
||||||
File libJarFile = library.relativeFile(jarStore);
|
|
||||||
File libSha1File = new File(nativesDir, libJarFile.getName() + ".sha1");
|
|
||||||
|
|
||||||
if (!libSha1File.exists()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
String sha1 = FileUtils.readFileToString(libSha1File, StandardCharsets.UTF_8);
|
|
||||||
|
|
||||||
if (!sha1.equalsIgnoreCase(library.sha1())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
project.getLogger().error("Failed to read " + libSha1File.getAbsolutePath(), e);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// All looks good, no need to re-extract
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<MinecraftVersionMeta.Download> getNatives() {
|
|
||||||
return extension.getMinecraftProvider().getVersionInfo().libraries().stream()
|
|
||||||
.filter((MinecraftVersionMeta.Library::hasNativesForOS))
|
|
||||||
.map(MinecraftVersionMeta.Library::classifierForOS)
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -81,7 +81,7 @@ public record MinecraftVersionMeta(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (natives.get(OperatingSystem.getOS()) == null) {
|
if (natives.get(OperatingSystem.CURRENT_OS) == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ public record MinecraftVersionMeta(
|
||||||
}
|
}
|
||||||
|
|
||||||
public Download classifierForOS() {
|
public Download classifierForOS() {
|
||||||
return downloads().classifier(natives.get(OperatingSystem.getOS()));
|
return downloads().classifier(natives.get(OperatingSystem.CURRENT_OS));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Download artifact() {
|
public Download artifact() {
|
||||||
|
@ -119,7 +119,7 @@ public record MinecraftVersionMeta(
|
||||||
|
|
||||||
public record OS(String name) {
|
public record OS(String name) {
|
||||||
public boolean isValidForOS() {
|
public boolean isValidForOS() {
|
||||||
return name() == null || name().equalsIgnoreCase(OperatingSystem.getOS());
|
return name() == null || name().equalsIgnoreCase(OperatingSystem.CURRENT_OS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ public interface LoomFiles {
|
||||||
File getProjectPersistentCache();
|
File getProjectPersistentCache();
|
||||||
File getProjectBuildCache();
|
File getProjectBuildCache();
|
||||||
File getRemappedModCache();
|
File getRemappedModCache();
|
||||||
File getNativesJarStore();
|
File getNativesDirectory(Project project);
|
||||||
File getDefaultLog4jConfigFile();
|
File getDefaultLog4jConfigFile();
|
||||||
File getDevLauncherConfig();
|
File getDevLauncherConfig();
|
||||||
File getUnpickLoggingConfigFile();
|
File getUnpickLoggingConfigFile();
|
||||||
|
|
|
@ -26,6 +26,10 @@ package net.fabricmc.loom.extension;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.gradle.api.Project;
|
||||||
|
|
||||||
|
import net.fabricmc.loom.LoomGradleExtension;
|
||||||
|
|
||||||
public abstract class LoomFilesBaseImpl implements LoomFiles {
|
public abstract class LoomFilesBaseImpl implements LoomFiles {
|
||||||
protected abstract File getGradleUserHomeDir();
|
protected abstract File getGradleUserHomeDir();
|
||||||
protected abstract File getRootDir();
|
protected abstract File getRootDir();
|
||||||
|
@ -70,8 +74,8 @@ public abstract class LoomFilesBaseImpl implements LoomFiles {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getNativesJarStore() {
|
public File getNativesDirectory(Project project) {
|
||||||
return createFile(getUserCache(), "natives/jars");
|
return createFile(getRootProjectPersistentCache(), "natives/" + LoomGradleExtension.get(project).getMinecraftProvider().minecraftVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -37,6 +37,7 @@ import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.cadixdev.lorenz.MappingSet;
|
import org.cadixdev.lorenz.MappingSet;
|
||||||
import org.cadixdev.mercury.Mercury;
|
import org.cadixdev.mercury.Mercury;
|
||||||
|
import org.gradle.api.Action;
|
||||||
import org.gradle.api.NamedDomainObjectProvider;
|
import org.gradle.api.NamedDomainObjectProvider;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.artifacts.Configuration;
|
import org.gradle.api.artifacts.Configuration;
|
||||||
|
@ -145,8 +146,8 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NamedDomainObjectProvider<Configuration> createLazyConfiguration(String name) {
|
public NamedDomainObjectProvider<Configuration> createLazyConfiguration(String name, Action<? super Configuration> configurationAction) {
|
||||||
NamedDomainObjectProvider<Configuration> provider = project.getConfigurations().register(name);
|
NamedDomainObjectProvider<Configuration> provider = project.getConfigurations().register(name, configurationAction);
|
||||||
|
|
||||||
if (lazyConfigurations.containsKey(name)) {
|
if (lazyConfigurations.containsKey(name)) {
|
||||||
throw new IllegalStateException("Duplicate configuration name" + name);
|
throw new IllegalStateException("Duplicate configuration name" + name);
|
||||||
|
|
|
@ -29,7 +29,7 @@ import java.util.Objects;
|
||||||
import org.gradle.api.Action;
|
import org.gradle.api.Action;
|
||||||
import org.gradle.api.InvalidUserDataException;
|
import org.gradle.api.InvalidUserDataException;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.plugins.JavaPluginConvention;
|
import org.gradle.api.plugins.JavaPluginExtension;
|
||||||
import org.gradle.api.provider.Property;
|
import org.gradle.api.provider.Property;
|
||||||
import org.gradle.api.provider.Provider;
|
import org.gradle.api.provider.Provider;
|
||||||
import org.gradle.api.tasks.SourceSet;
|
import org.gradle.api.tasks.SourceSet;
|
||||||
|
@ -110,8 +110,7 @@ public abstract class MixinExtensionApiImpl implements MixinExtensionAPI {
|
||||||
|
|
||||||
private SourceSet resolveSourceSet(String sourceSetName) {
|
private SourceSet resolveSourceSet(String sourceSetName) {
|
||||||
// try to find sourceSet with name sourceSetName in this project
|
// try to find sourceSet with name sourceSetName in this project
|
||||||
SourceSet sourceSet = project.getConvention().getPlugin(JavaPluginConvention.class)
|
SourceSet sourceSet = project.getExtensions().getByType(JavaPluginExtension.class).getSourceSets().findByName(sourceSetName);
|
||||||
.getSourceSets().findByName(sourceSetName);
|
|
||||||
|
|
||||||
if (sourceSet == null) {
|
if (sourceSet == null) {
|
||||||
throw new InvalidUserDataException("No sourceSet " + sourceSetName + " was found");
|
throw new InvalidUserDataException("No sourceSet " + sourceSetName + " was found");
|
||||||
|
|
|
@ -38,8 +38,8 @@ import org.gradle.api.Project;
|
||||||
import org.gradle.api.Task;
|
import org.gradle.api.Task;
|
||||||
import org.gradle.api.UnknownTaskException;
|
import org.gradle.api.UnknownTaskException;
|
||||||
import org.gradle.api.artifacts.Configuration;
|
import org.gradle.api.artifacts.Configuration;
|
||||||
import org.gradle.api.plugins.BasePluginConvention;
|
import org.gradle.api.plugins.BasePluginExtension;
|
||||||
import org.gradle.api.plugins.JavaPluginConvention;
|
import org.gradle.api.plugins.JavaPluginExtension;
|
||||||
import org.gradle.api.provider.Property;
|
import org.gradle.api.provider.Property;
|
||||||
import org.gradle.api.provider.Provider;
|
import org.gradle.api.provider.Provider;
|
||||||
import org.gradle.api.tasks.Input;
|
import org.gradle.api.tasks.Input;
|
||||||
|
@ -67,7 +67,7 @@ public class MixinExtensionImpl extends MixinExtensionApiImpl implements MixinEx
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getDefaultMixinRefmapName() {
|
private String getDefaultMixinRefmapName() {
|
||||||
String defaultRefmapName = project.getConvention().getPlugin(BasePluginConvention.class).getArchivesBaseName() + "-refmap.json";
|
String defaultRefmapName = project.getExtensions().getByType(BasePluginExtension.class).getArchivesName().get() + "-refmap.json";
|
||||||
project.getLogger().info("Could not find refmap definition, will be using default name: " + defaultRefmapName);
|
project.getLogger().info("Could not find refmap definition, will be using default name: " + defaultRefmapName);
|
||||||
return defaultRefmapName;
|
return defaultRefmapName;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ public class MixinExtensionImpl extends MixinExtensionApiImpl implements MixinEx
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public Stream<SourceSet> getMixinSourceSetsStream() {
|
public Stream<SourceSet> getMixinSourceSetsStream() {
|
||||||
return project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().stream()
|
return project.getExtensions().getByType(JavaPluginExtension.class).getSourceSets().stream()
|
||||||
.filter(sourceSet -> MixinExtension.getMixinInformationContainer(sourceSet) != null);
|
.filter(sourceSet -> MixinExtension.getMixinInformationContainer(sourceSet) != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ public class MixinExtensionImpl extends MixinExtensionApiImpl implements MixinEx
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init() {
|
||||||
if (isDefault) {
|
if (isDefault) {
|
||||||
project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().forEach(this::add);
|
project.getExtensions().getByType(JavaPluginExtension.class).getSourceSets().forEach(this::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
isDefault = false;
|
isDefault = false;
|
||||||
|
|
|
@ -46,6 +46,7 @@ public abstract class AbstractRunTask extends JavaExec {
|
||||||
|
|
||||||
setClasspath(config.sourceSet.getRuntimeClasspath());
|
setClasspath(config.sourceSet.getRuntimeClasspath());
|
||||||
args(config.programArgs);
|
args(config.programArgs);
|
||||||
|
getMainClass().set(config.mainClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -64,11 +65,6 @@ public abstract class AbstractRunTask extends JavaExec {
|
||||||
super.setWorkingDir(dir);
|
super.setWorkingDir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMain() {
|
|
||||||
return config.mainClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getJvmArgs() {
|
public List<String> getJvmArgs() {
|
||||||
List<String> superArgs = super.getJvmArgs();
|
List<String> superArgs = super.getJvmArgs();
|
||||||
|
|
|
@ -30,7 +30,6 @@ import org.gradle.api.Project;
|
||||||
import org.gradle.api.tasks.TaskAction;
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
|
||||||
import net.fabricmc.loom.LoomGradleExtension;
|
import net.fabricmc.loom.LoomGradleExtension;
|
||||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftNativesProvider;
|
|
||||||
import net.fabricmc.loom.configuration.providers.minecraft.assets.MinecraftAssetsProvider;
|
import net.fabricmc.loom.configuration.providers.minecraft.assets.MinecraftAssetsProvider;
|
||||||
|
|
||||||
public class DownloadAssetsTask extends AbstractLoomTask {
|
public class DownloadAssetsTask extends AbstractLoomTask {
|
||||||
|
@ -40,6 +39,5 @@ public class DownloadAssetsTask extends AbstractLoomTask {
|
||||||
LoomGradleExtension extension = getExtension();
|
LoomGradleExtension extension = getExtension();
|
||||||
|
|
||||||
MinecraftAssetsProvider.provide(extension.getMinecraftProvider(), project);
|
MinecraftAssetsProvider.provide(extension.getMinecraftProvider(), project);
|
||||||
MinecraftNativesProvider.provide(project);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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.task;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.gradle.api.tasks.Sync;
|
||||||
|
|
||||||
|
import net.fabricmc.loom.LoomGradleExtension;
|
||||||
|
import net.fabricmc.loom.util.Constants;
|
||||||
|
|
||||||
|
public abstract class ExtractNativesTask extends Sync {
|
||||||
|
@Inject
|
||||||
|
public ExtractNativesTask() {
|
||||||
|
// Is there a lazy way to do this for many files? - Doesnt seem there is...
|
||||||
|
for (File nativeFile : getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_NATIVES).getFiles()) {
|
||||||
|
from(getProject().zipTree(nativeFile), copySpec -> {
|
||||||
|
copySpec.exclude("META-INF/**");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
into(LoomGradleExtension.get(getProject()).getFiles().getNativesDirectory(getProject()));
|
||||||
|
|
||||||
|
setDescription("Downloads and extracts the minecraft natives");
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,6 +43,7 @@ public final class LoomTasks {
|
||||||
|
|
||||||
public static void registerTasks(Project project) {
|
public static void registerTasks(Project project) {
|
||||||
TaskContainer tasks = project.getTasks();
|
TaskContainer tasks = project.getTasks();
|
||||||
|
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||||
|
|
||||||
tasks.register("migrateMappings", MigrateMappingsTask.class, t -> {
|
tasks.register("migrateMappings", MigrateMappingsTask.class, t -> {
|
||||||
t.setDescription("Migrates mappings to a new version.");
|
t.setDescription("Migrates mappings to a new version.");
|
||||||
|
@ -54,7 +55,11 @@ public final class LoomTasks {
|
||||||
t.setGroup(Constants.TaskGroup.FABRIC);
|
t.setGroup(Constants.TaskGroup.FABRIC);
|
||||||
});
|
});
|
||||||
|
|
||||||
tasks.register("downloadAssets", DownloadAssetsTask.class, t -> t.setDescription("Downloads required assets for Fabric."));
|
TaskProvider<ExtractNativesTask> extractNatives = tasks.register("extractNatives", ExtractNativesTask.class);
|
||||||
|
tasks.register("downloadAssets", DownloadAssetsTask.class, t -> {
|
||||||
|
t.dependsOn(extractNatives);
|
||||||
|
t.setDescription("Downloads required assets for Fabric.");
|
||||||
|
});
|
||||||
tasks.register("remapSourcesJar", RemapSourcesJarTask.class, t -> t.setDescription("Remaps the project sources jar to intermediary names."));
|
tasks.register("remapSourcesJar", RemapSourcesJarTask.class, t -> t.setDescription("Remaps the project sources jar to intermediary names."));
|
||||||
|
|
||||||
TaskProvider<ValidateAccessWidenerTask> validateAccessWidener = tasks.register("validateAccessWidener", ValidateAccessWidenerTask.class, t -> {
|
TaskProvider<ValidateAccessWidenerTask> validateAccessWidener = tasks.register("validateAccessWidener", ValidateAccessWidenerTask.class, t -> {
|
||||||
|
|
|
@ -42,7 +42,7 @@ import org.gradle.api.IllegalDependencyNotation;
|
||||||
import org.gradle.api.JavaVersion;
|
import org.gradle.api.JavaVersion;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.artifacts.Dependency;
|
import org.gradle.api.artifacts.Dependency;
|
||||||
import org.gradle.api.plugins.JavaPluginConvention;
|
import org.gradle.api.plugins.JavaPluginExtension;
|
||||||
import org.gradle.api.tasks.TaskAction;
|
import org.gradle.api.tasks.TaskAction;
|
||||||
import org.gradle.api.tasks.options.Option;
|
import org.gradle.api.tasks.options.Option;
|
||||||
|
|
||||||
|
@ -171,12 +171,7 @@ public class MigrateMappingsTask extends AbstractLoomTask {
|
||||||
project.getLogger().lifecycle(":remapping");
|
project.getLogger().lifecycle(":remapping");
|
||||||
Mercury mercury = SourceRemapper.createMercuryWithClassPath(project, false);
|
Mercury mercury = SourceRemapper.createMercuryWithClassPath(project, false);
|
||||||
|
|
||||||
final JavaPluginConvention convention = project.getConvention().findPlugin(JavaPluginConvention.class);
|
final JavaVersion javaVersion = project.getExtensions().getByType(JavaPluginExtension.class).getSourceCompatibility();
|
||||||
final JavaVersion javaVersion = convention != null
|
|
||||||
?
|
|
||||||
convention.getSourceCompatibility()
|
|
||||||
:
|
|
||||||
JavaVersion.current();
|
|
||||||
mercury.setSourceCompatibility(javaVersion.toString());
|
mercury.setSourceCompatibility(javaVersion.toString());
|
||||||
|
|
||||||
mercury.getClassPath().add(minecraftMappedProvider.getMappedJar().toPath());
|
mercury.getClassPath().add(minecraftMappedProvider.getMappedJar().toPath());
|
||||||
|
|
|
@ -124,7 +124,7 @@ public class RemapJarTask extends Jar {
|
||||||
Project project = getProject();
|
Project project = getProject();
|
||||||
LoomGradleExtension extension = LoomGradleExtension.get(getProject());
|
LoomGradleExtension extension = LoomGradleExtension.get(getProject());
|
||||||
Path input = this.getInput().getAsFile().get().toPath();
|
Path input = this.getInput().getAsFile().get().toPath();
|
||||||
Path output = this.getArchivePath().toPath();
|
Path output = this.getArchiveFile().get().getAsFile().toPath();
|
||||||
|
|
||||||
if (!Files.exists(input)) {
|
if (!Files.exists(input)) {
|
||||||
throw new FileNotFoundException(input.toString());
|
throw new FileNotFoundException(input.toString());
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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.util;
|
||||||
|
|
||||||
|
public class Architecture {
|
||||||
|
public static final Architecture CURRENT = new Architecture(System.getProperty("os.arch"));
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public Architecture(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean is64Bit() {
|
||||||
|
return name.contains("64") || name.startsWith("armv8");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isArm() {
|
||||||
|
return name.startsWith("arm") || name.startsWith("aarch64");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* 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.util;
|
||||||
|
|
||||||
|
import groovy.lang.Closure;
|
||||||
|
import org.gradle.api.Action;
|
||||||
|
|
||||||
|
public record ClosureAction<T>(Closure closure) implements Action<T> {
|
||||||
|
@Override
|
||||||
|
public void execute(T t) {
|
||||||
|
closure.setDelegate(t);
|
||||||
|
closure.call(t);
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,8 +40,6 @@ public class Constants {
|
||||||
public static final String EXPERIMENTAL_VERSIONS = "https://maven.fabricmc.net/net/minecraft/experimental_versions.json";
|
public static final String EXPERIMENTAL_VERSIONS = "https://maven.fabricmc.net/net/minecraft/experimental_versions.json";
|
||||||
public static final String FABRIC_REPOSITORY = "https://maven.fabricmc.net/";
|
public static final String FABRIC_REPOSITORY = "https://maven.fabricmc.net/";
|
||||||
|
|
||||||
public static final String SYSTEM_ARCH = System.getProperty("os.arch").equals("64") ? "64" : "32";
|
|
||||||
|
|
||||||
public static final int ASM_VERSION = Opcodes.ASM9;
|
public static final int ASM_VERSION = Opcodes.ASM9;
|
||||||
|
|
||||||
public static final List<RemappedConfigurationEntry> MOD_COMPILE_ENTRIES = ImmutableList.of(
|
public static final List<RemappedConfigurationEntry> MOD_COMPILE_ENTRIES = ImmutableList.of(
|
||||||
|
@ -64,8 +62,13 @@ public class Constants {
|
||||||
public static final String MOD_COMPILE_CLASSPATH_MAPPED = "modCompileClasspathMapped";
|
public static final String MOD_COMPILE_CLASSPATH_MAPPED = "modCompileClasspathMapped";
|
||||||
public static final String INCLUDE = "include";
|
public static final String INCLUDE = "include";
|
||||||
public static final String MINECRAFT = "minecraft";
|
public static final String MINECRAFT = "minecraft";
|
||||||
|
/**
|
||||||
|
* The server specific configuration will be empty when using a legacy (pre 21w38a server jar)
|
||||||
|
* find the client only dependencies on the "minecraftLibraries" config.
|
||||||
|
*/
|
||||||
|
public static final String MINECRAFT_SERVER_DEPENDENCIES = "minecraftServerLibraries";
|
||||||
public static final String MINECRAFT_DEPENDENCIES = "minecraftLibraries";
|
public static final String MINECRAFT_DEPENDENCIES = "minecraftLibraries";
|
||||||
public static final String MINECRAFT_REMAP_CLASSPATH = "minecraftRemapClasspath";
|
public static final String MINECRAFT_NATIVES = "minecraftNatives";
|
||||||
public static final String MINECRAFT_NAMED = "minecraftNamed";
|
public static final String MINECRAFT_NAMED = "minecraftNamed";
|
||||||
public static final String MAPPINGS = "mappings";
|
public static final String MAPPINGS = "mappings";
|
||||||
public static final String MAPPINGS_FINAL = "mappingsFinal";
|
public static final String MAPPINGS_FINAL = "mappingsFinal";
|
||||||
|
@ -93,6 +96,7 @@ public class Constants {
|
||||||
public static final String DEV_LAUNCH_INJECTOR = "net.fabricmc:dev-launch-injector:";
|
public static final String DEV_LAUNCH_INJECTOR = "net.fabricmc:dev-launch-injector:";
|
||||||
public static final String TERMINAL_CONSOLE_APPENDER = "net.minecrell:terminalconsoleappender:";
|
public static final String TERMINAL_CONSOLE_APPENDER = "net.minecrell:terminalconsoleappender:";
|
||||||
public static final String JETBRAINS_ANNOTATIONS = "org.jetbrains:annotations:";
|
public static final String JETBRAINS_ANNOTATIONS = "org.jetbrains:annotations:";
|
||||||
|
public static final String NATIVE_SUPPORT = "net.fabricmc:fabric-loom-native-support:";
|
||||||
|
|
||||||
private Dependencies() {
|
private Dependencies() {
|
||||||
}
|
}
|
||||||
|
@ -105,6 +109,7 @@ public class Constants {
|
||||||
public static final String DEV_LAUNCH_INJECTOR = "0.2.1+build.8";
|
public static final String DEV_LAUNCH_INJECTOR = "0.2.1+build.8";
|
||||||
public static final String TERMINAL_CONSOLE_APPENDER = "1.2.0";
|
public static final String TERMINAL_CONSOLE_APPENDER = "1.2.0";
|
||||||
public static final String JETBRAINS_ANNOTATIONS = "23.0.0";
|
public static final String JETBRAINS_ANNOTATIONS = "23.0.0";
|
||||||
|
public static final String NATIVE_SUPPORT_VERSION = "1.0.1";
|
||||||
|
|
||||||
private Versions() {
|
private Versions() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,12 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.FileSystem;
|
import java.nio.file.FileSystem;
|
||||||
import java.nio.file.FileSystemAlreadyExistsException;
|
import java.nio.file.FileSystemAlreadyExistsException;
|
||||||
import java.nio.file.FileSystems;
|
import java.nio.file.FileSystems;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.NoSuchFileException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -38,6 +41,20 @@ import java.util.function.Supplier;
|
||||||
|
|
||||||
public final class FileSystemUtil {
|
public final class FileSystemUtil {
|
||||||
public record Delegate(FileSystem fs, boolean owner) implements AutoCloseable, Supplier<FileSystem> {
|
public record Delegate(FileSystem fs, boolean owner) implements AutoCloseable, Supplier<FileSystem> {
|
||||||
|
public byte[] readAllBytes(String path) throws IOException {
|
||||||
|
Path fsPath = get().getPath(path);
|
||||||
|
|
||||||
|
if (Files.exists(fsPath)) {
|
||||||
|
return Files.readAllBytes(fsPath);
|
||||||
|
} else {
|
||||||
|
throw new NoSuchFileException(fsPath.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readString(String path) throws IOException {
|
||||||
|
return new String(readAllBytes(path), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
if (owner) {
|
if (owner) {
|
||||||
|
@ -65,6 +82,10 @@ public final class FileSystemUtil {
|
||||||
return getJarFileSystem(path.toUri(), create);
|
return getJarFileSystem(path.toUri(), create);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Delegate getJarFileSystem(Path path) throws IOException {
|
||||||
|
return getJarFileSystem(path, false);
|
||||||
|
}
|
||||||
|
|
||||||
public static Delegate getJarFileSystem(URI uri, boolean create) throws IOException {
|
public static Delegate getJarFileSystem(URI uri, boolean create) throws IOException {
|
||||||
URI jarUri;
|
URI jarUri;
|
||||||
|
|
||||||
|
|
|
@ -25,18 +25,12 @@
|
||||||
package net.fabricmc.loom.util;
|
package net.fabricmc.loom.util;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.zip.ZipFile;
|
|
||||||
|
|
||||||
public final class ModUtils {
|
public final class ModUtils {
|
||||||
private ModUtils() {
|
private ModUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isMod(File input) {
|
public static boolean isMod(File input) {
|
||||||
try (ZipFile zipFile = new ZipFile(input)) {
|
return ZipUtils.contains(input.toPath(), "fabric.mod.json");
|
||||||
return zipFile.getEntry("fabric.mod.json") != null;
|
|
||||||
} catch (IOException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,23 +30,21 @@ import java.net.StandardProtocolFamily;
|
||||||
import java.nio.channels.ServerSocketChannel;
|
import java.nio.channels.ServerSocketChannel;
|
||||||
|
|
||||||
public class OperatingSystem {
|
public class OperatingSystem {
|
||||||
public static String getOS() {
|
public static final String WINDOWS = "windows";
|
||||||
|
public static final String MAC_OS = "osx";
|
||||||
|
public static final String LINUX = "linux";
|
||||||
|
|
||||||
|
public static final String CURRENT_OS = getOS();
|
||||||
|
|
||||||
|
private static String getOS() {
|
||||||
String osName = System.getProperty("os.name").toLowerCase();
|
String osName = System.getProperty("os.name").toLowerCase();
|
||||||
|
|
||||||
if (osName.contains("win")) {
|
if (osName.contains("win")) {
|
||||||
return "windows";
|
return WINDOWS;
|
||||||
} else if (osName.contains("mac")) {
|
} else if (osName.contains("mac")) {
|
||||||
return "osx";
|
return MAC_OS;
|
||||||
} else {
|
} else {
|
||||||
return "linux";
|
return LINUX;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getArch() {
|
|
||||||
if (is64Bit()) {
|
|
||||||
return "64";
|
|
||||||
} else {
|
|
||||||
return "32";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +52,6 @@ public class OperatingSystem {
|
||||||
return System.getProperty("sun.arch.data.model").contains("64");
|
return System.getProperty("sun.arch.data.model").contains("64");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isWindows() {
|
|
||||||
return getOS().equals("windows");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isCIBuild() {
|
public static boolean isCIBuild() {
|
||||||
String loomProperty = System.getProperty("fabric.loom.ci");
|
String loomProperty = System.getProperty("fabric.loom.ci");
|
||||||
|
|
||||||
|
|
|
@ -83,13 +83,7 @@ public class ZipUtils {
|
||||||
|
|
||||||
public static byte[] unpack(Path zip, String path) throws IOException {
|
public static byte[] unpack(Path zip, String path) throws IOException {
|
||||||
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(zip, false)) {
|
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(zip, false)) {
|
||||||
Path fsPath = fs.get().getPath(path);
|
return fs.readAllBytes(path);
|
||||||
|
|
||||||
if (Files.exists(fsPath)) {
|
|
||||||
return Files.readAllBytes(fsPath);
|
|
||||||
} else {
|
|
||||||
throw new NoSuchFileException(fsPath.toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ import org.gradle.util.GradleVersion
|
||||||
|
|
||||||
class LoomTestConstants {
|
class LoomTestConstants {
|
||||||
public final static String DEFAULT_GRADLE = GradleVersion.current().getVersion()
|
public final static String DEFAULT_GRADLE = GradleVersion.current().getVersion()
|
||||||
public final static String PRE_RELEASE_GRADLE = "7.4-20211203231050+0000"
|
public final static String PRE_RELEASE_GRADLE = "7.4-20211216231505+0000"
|
||||||
|
|
||||||
public final static String[] STANDARD_TEST_VERSIONS = [DEFAULT_GRADLE, PRE_RELEASE_GRADLE]
|
public final static String[] STANDARD_TEST_VERSIONS = [DEFAULT_GRADLE, PRE_RELEASE_GRADLE]
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* 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.GradleProjectTestTrait
|
||||||
|
import spock.lang.Specification
|
||||||
|
import spock.lang.Unroll
|
||||||
|
import spock.util.environment.RestoreSystemProperties
|
||||||
|
|
||||||
|
import static net.fabricmc.loom.test.LoomTestConstants.STANDARD_TEST_VERSIONS
|
||||||
|
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
|
||||||
|
import static org.gradle.testkit.runner.TaskOutcome.UP_TO_DATE
|
||||||
|
|
||||||
|
class NativesTest extends Specification implements GradleProjectTestTrait {
|
||||||
|
@Unroll
|
||||||
|
def "Default natives for 1.18 (gradle #version)"() {
|
||||||
|
setup:
|
||||||
|
def gradle = gradleProject(project: "minimalBase", version: version)
|
||||||
|
|
||||||
|
gradle.buildGradle << '''
|
||||||
|
dependencies {
|
||||||
|
minecraft "com.mojang:minecraft:1.18"
|
||||||
|
mappings loom.officialMojangMappings()
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
when:
|
||||||
|
// Run the task twice to ensure its up to date
|
||||||
|
def result = gradle.run(task: "extractNatives")
|
||||||
|
def result2 = gradle.run(task: "extractNatives")
|
||||||
|
|
||||||
|
then:
|
||||||
|
result.task(":extractNatives").outcome == SUCCESS
|
||||||
|
result2.task(":extractNatives").outcome == UP_TO_DATE
|
||||||
|
|
||||||
|
where:
|
||||||
|
version << STANDARD_TEST_VERSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestoreSystemProperties
|
||||||
|
@Unroll
|
||||||
|
def "Overridden natives for 1.18 (gradle #version)"() {
|
||||||
|
setup:
|
||||||
|
System.setProperty('loom.test.lwjgloverride', "true")
|
||||||
|
def gradle = gradleProject(project: "minimalBase", version: version)
|
||||||
|
|
||||||
|
gradle.buildGradle << '''
|
||||||
|
dependencies {
|
||||||
|
minecraft "com.mojang:minecraft:1.18"
|
||||||
|
mappings loom.officialMojangMappings()
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
when:
|
||||||
|
// Run the task twice to ensure its up to date
|
||||||
|
def result = gradle.run(task: "extractNatives")
|
||||||
|
|
||||||
|
then:
|
||||||
|
result.task(":extractNatives").outcome == SUCCESS
|
||||||
|
|
||||||
|
where:
|
||||||
|
version << STANDARD_TEST_VERSIONS
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,29 +30,29 @@ import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuil
|
||||||
import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec
|
import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec
|
||||||
import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec
|
import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec
|
||||||
import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpec
|
import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpec
|
||||||
import org.gradle.api.Action
|
import net.fabricmc.loom.util.ClosureAction
|
||||||
import org.gradle.util.ConfigureUtil
|
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
class LayeredMappingSpecBuilderTest extends Specification {
|
class LayeredMappingSpecBuilderTest extends Specification {
|
||||||
def "simple mojmap" () {
|
def "simple mojmap" () {
|
||||||
when:
|
when:
|
||||||
def spec = layered() {
|
def spec = layered {
|
||||||
officialMojangMappings()
|
officialMojangMappings()
|
||||||
}
|
}
|
||||||
def layers = spec.layers()
|
def layers = spec.layers()
|
||||||
then:
|
then:
|
||||||
spec.version == "layered+hash.2198"
|
|
||||||
layers.size() == 2
|
layers.size() == 2
|
||||||
|
spec.version == "layered+hash.2198"
|
||||||
layers[0].class == IntermediaryMappingsSpec
|
layers[0].class == IntermediaryMappingsSpec
|
||||||
layers[1].class == MojangMappingsSpec
|
layers[1].class == MojangMappingsSpec
|
||||||
}
|
}
|
||||||
|
|
||||||
def "simple mojmap with parchment" () {
|
def "simple mojmap with parchment" () {
|
||||||
when:
|
when:
|
||||||
|
def dep = "I like cake"
|
||||||
def spec = layered() {
|
def spec = layered() {
|
||||||
officialMojangMappings()
|
officialMojangMappings()
|
||||||
parchment("I like cake")
|
parchment(dep)
|
||||||
}
|
}
|
||||||
def layers = spec.layers()
|
def layers = spec.layers()
|
||||||
def parchment = layers[2] as ParchmentMappingsSpec
|
def parchment = layers[2] as ParchmentMappingsSpec
|
||||||
|
@ -88,7 +88,7 @@ class LayeredMappingSpecBuilderTest extends Specification {
|
||||||
|
|
||||||
def "simple mojmap with parchment keep prefix alternate hash" () {
|
def "simple mojmap with parchment keep prefix alternate hash" () {
|
||||||
when:
|
when:
|
||||||
def spec = layered() {
|
def spec = layered {
|
||||||
officialMojangMappings()
|
officialMojangMappings()
|
||||||
parchment("I really like cake") {
|
parchment("I really like cake") {
|
||||||
it.removePrefix = false
|
it.removePrefix = false
|
||||||
|
@ -106,14 +106,9 @@ class LayeredMappingSpecBuilderTest extends Specification {
|
||||||
parchment.removePrefix() == false
|
parchment.removePrefix() == false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gradle does this big of magic behind the scenes
|
|
||||||
LayeredMappingSpec layered(@DelegatesTo(LayeredMappingSpecBuilderImpl) Closure cl) {
|
LayeredMappingSpec layered(@DelegatesTo(LayeredMappingSpecBuilderImpl) Closure cl) {
|
||||||
return layeredAction(ConfigureUtil.configureUsing(cl))
|
|
||||||
}
|
|
||||||
|
|
||||||
LayeredMappingSpec layeredAction(Action<LayeredMappingSpecBuilderImpl> action) {
|
|
||||||
LayeredMappingSpecBuilderImpl builder = new LayeredMappingSpecBuilderImpl()
|
LayeredMappingSpecBuilderImpl builder = new LayeredMappingSpecBuilderImpl()
|
||||||
action.execute(builder)
|
new ClosureAction(cl).execute(builder)
|
||||||
return builder.build()
|
return builder.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue