From ab4234330ee208d97a08991ed77f607cd1365828 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Mon, 3 Oct 2022 22:00:07 +0100 Subject: [PATCH] First look at MinecraftJarProcessor API --- .../fabricmc/loom/LoomGradleExtension.java | 9 +- .../loom/api/LoomGradleExtensionAPI.java | 9 +- .../api/processor/MinecraftJarProcessor.java | 53 +++++++ .../loom/api/processor/ProcessorContext.java | 37 +++++ .../loom/api/processor/SpecContext.java | 35 +++++ .../configuration/CompileConfiguration.java | 18 +-- .../SingleJarDecompileConfiguration.java | 2 +- .../processors/JarProcessor.java | 1 + .../processors/JarProcessorManager.java | 129 ---------------- .../processors/LegacyJarProcessorWrapper.java | 65 ++++++++ .../MinecraftJarProcessorManager.java | 145 ++++++++++++++++++ .../processors/ProcessorContextImpl.java | 58 +++++++ .../processors/SpecContextImpl.java | 44 ++++++ .../providers/minecraft/MinecraftJar.java | 80 ++++++++++ .../minecraft/MinecraftJarConfiguration.java | 10 +- .../providers/minecraft/SingleJarEnvType.java | 43 ++++++ .../minecraft/SingleJarMinecraftProvider.java | 14 +- .../mapped/IntermediaryMinecraftProvider.java | 11 +- .../mapped/MappedMinecraftProvider.java | 23 ++- .../mapped/NamedMinecraftProvider.java | 11 +- .../ProcessedNamedMinecraftProvider.java | 97 ++++++------ .../extension/LoomGradleExtensionApiImpl.java | 19 +++ .../extension/LoomGradleExtensionImpl.java | 12 -- .../fabricmc/loom/util/DeprecationHelper.java | 4 +- 24 files changed, 691 insertions(+), 238 deletions(-) create mode 100644 src/main/java/net/fabricmc/loom/api/processor/MinecraftJarProcessor.java create mode 100644 src/main/java/net/fabricmc/loom/api/processor/ProcessorContext.java create mode 100644 src/main/java/net/fabricmc/loom/api/processor/SpecContext.java delete mode 100644 src/main/java/net/fabricmc/loom/configuration/processors/JarProcessorManager.java create mode 100644 src/main/java/net/fabricmc/loom/configuration/processors/LegacyJarProcessorWrapper.java create mode 100644 src/main/java/net/fabricmc/loom/configuration/processors/MinecraftJarProcessorManager.java create mode 100644 src/main/java/net/fabricmc/loom/configuration/processors/ProcessorContextImpl.java create mode 100644 src/main/java/net/fabricmc/loom/configuration/processors/SpecContextImpl.java create mode 100644 src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftJar.java create mode 100644 src/main/java/net/fabricmc/loom/configuration/providers/minecraft/SingleJarEnvType.java diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java index 72546cdb..33a1282f 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java +++ b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java @@ -39,7 +39,6 @@ import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.InstallerData; import net.fabricmc.loom.configuration.LoomDependencyManager; import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile; -import net.fabricmc.loom.configuration.processors.JarProcessorManager; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.mapped.IntermediaryMinecraftProvider; @@ -69,10 +68,6 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI { LoomDependencyManager getDependencyManager(); - void setJarProcessorManager(JarProcessorManager jarProcessorManager); - - JarProcessorManager getJarProcessorManager(); - MinecraftProvider getMinecraftProvider(); void setMinecraftProvider(MinecraftProvider minecraftProvider); @@ -91,8 +86,8 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI { default List getMinecraftJars(MappingsNamespace mappingsNamespace) { return switch (mappingsNamespace) { - case NAMED -> getNamedMinecraftProvider().getMinecraftJars(); - case INTERMEDIARY -> getIntermediaryMinecraftProvider().getMinecraftJars(); + case NAMED -> getNamedMinecraftProvider().getMinecraftJarPaths(); + case INTERMEDIARY -> getIntermediaryMinecraftProvider().getMinecraftJarPaths(); case OFFICIAL -> getMinecraftProvider().getMinecraftJars(); }; } diff --git a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java index 693f1d55..006a0c60 100644 --- a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java +++ b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java @@ -42,6 +42,7 @@ import org.jetbrains.annotations.ApiStatus; import net.fabricmc.loom.api.decompilers.DecompilerOptions; import net.fabricmc.loom.api.mappings.intermediate.IntermediateMappingsProvider; import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder; +import net.fabricmc.loom.api.processor.MinecraftJarProcessor; import net.fabricmc.loom.configuration.ide.RunConfigSettings; import net.fabricmc.loom.configuration.processors.JarProcessor; import net.fabricmc.loom.configuration.providers.mappings.NoOpIntermediateMappingsProvider; @@ -62,11 +63,13 @@ public interface LoomGradleExtensionAPI { void decompilers(Action> action); + @Deprecated(forRemoval = true) ListProperty getGameJarProcessors(); - default void addJarProcessor(JarProcessor processor) { - getGameJarProcessors().add(processor); - } + @Deprecated(forRemoval = true) + void addJarProcessor(JarProcessor processor); + + ListProperty> getMinecraftJarProcessors(); ConfigurableFileCollection getLog4jConfigs(); diff --git a/src/main/java/net/fabricmc/loom/api/processor/MinecraftJarProcessor.java b/src/main/java/net/fabricmc/loom/api/processor/MinecraftJarProcessor.java new file mode 100644 index 00000000..0a43306f --- /dev/null +++ b/src/main/java/net/fabricmc/loom/api/processor/MinecraftJarProcessor.java @@ -0,0 +1,53 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.api.processor; + +import java.io.IOException; +import java.nio.file.Path; + +import org.gradle.api.Named; +import org.jetbrains.annotations.Nullable; + +import net.fabricmc.mappingio.tree.MemoryMappingTree; + +public interface MinecraftJarProcessor extends Named { + @Nullable + S buildSpec(SpecContext context); + + void processJar(Path jar, S spec, ProcessorContext context) throws IOException; + + @Nullable + default MappingsProcessor processMappings() { + return null; + } + + interface Spec { + String cacheValue(); + } + + interface MappingsProcessor { + boolean transform(MemoryMappingTree mappings, S spec, ProcessorContext context); + } +} diff --git a/src/main/java/net/fabricmc/loom/api/processor/ProcessorContext.java b/src/main/java/net/fabricmc/loom/api/processor/ProcessorContext.java new file mode 100644 index 00000000..9444e58b --- /dev/null +++ b/src/main/java/net/fabricmc/loom/api/processor/ProcessorContext.java @@ -0,0 +1,37 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.api.processor; + +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration; + +public interface ProcessorContext { + MinecraftJarConfiguration getJarConfiguration(); + + boolean isMerged(); + + boolean includesClient(); + + boolean includesServer(); +} diff --git a/src/main/java/net/fabricmc/loom/api/processor/SpecContext.java b/src/main/java/net/fabricmc/loom/api/processor/SpecContext.java new file mode 100644 index 00000000..b803114c --- /dev/null +++ b/src/main/java/net/fabricmc/loom/api/processor/SpecContext.java @@ -0,0 +1,35 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.api.processor; + +import java.util.List; + +import net.fabricmc.loom.util.fmj.FabricModJson; + +public interface SpecContext { + List getModDependencies(); + + List getMods(); +} diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java index e54194cd..2bc79be0 100644 --- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java @@ -49,8 +49,9 @@ import net.fabricmc.loom.build.mixin.ScalaApInvoker; import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor; import net.fabricmc.loom.configuration.accesswidener.TransitiveAccessWidenerJarProcessor; import net.fabricmc.loom.configuration.ifaceinject.InterfaceInjectionProcessor; -import net.fabricmc.loom.configuration.processors.JarProcessorManager; +import net.fabricmc.loom.configuration.processors.MinecraftJarProcessorManager; import net.fabricmc.loom.configuration.processors.ModJavadocProcessor; +import net.fabricmc.loom.configuration.processors.SpecContextImpl; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; @@ -196,11 +197,12 @@ public final class CompileConfiguration { final IntermediaryMinecraftProvider intermediaryMinecraftProvider = jarConfiguration.getIntermediaryMinecraftProviderBiFunction().apply(project, minecraftProvider); NamedMinecraftProvider namedMinecraftProvider = jarConfiguration.getNamedMinecraftProviderBiFunction().apply(project, minecraftProvider); - final JarProcessorManager jarProcessorManager = createJarProcessorManager(project); + registerGameProcessors(project); + MinecraftJarProcessorManager minecraftJarProcessorManager = MinecraftJarProcessorManager.create(extension.getMinecraftJarProcessors().get(), new SpecContextImpl()); - if (jarProcessorManager.active()) { + if (minecraftJarProcessorManager != null) { // Wrap the named MC provider for one that will provide the processed jars - namedMinecraftProvider = jarConfiguration.getProcessedNamedMinecraftProviderBiFunction().apply(namedMinecraftProvider, jarProcessorManager); + namedMinecraftProvider = jarConfiguration.getProcessedNamedMinecraftProviderBiFunction().apply(namedMinecraftProvider, minecraftJarProcessorManager); } extension.setIntermediaryMinecraftProvider(intermediaryMinecraftProvider); @@ -210,7 +212,7 @@ public final class CompileConfiguration { namedMinecraftProvider.provide(true); } - private static JarProcessorManager createJarProcessorManager(Project project) { + private static void registerGameProcessors(Project project) { final LoomGradleExtension extension = LoomGradleExtension.get(project); if (extension.getAccessWidenerPath().isPresent()) { @@ -241,12 +243,6 @@ public final class CompileConfiguration { extension.getGameJarProcessors().add(javadocProcessor); } } - - JarProcessorManager processorManager = new JarProcessorManager(extension.getGameJarProcessors().get()); - extension.setJarProcessorManager(processorManager); - processorManager.setupProcessors(); - - return processorManager; } private static void setupMixinAp(Project project, MixinExtension mixin) { diff --git a/src/main/java/net/fabricmc/loom/configuration/decompile/SingleJarDecompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/decompile/SingleJarDecompileConfiguration.java index 782da709..b5f2dc32 100644 --- a/src/main/java/net/fabricmc/loom/configuration/decompile/SingleJarDecompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/decompile/SingleJarDecompileConfiguration.java @@ -42,7 +42,7 @@ public class SingleJarDecompileConfiguration extends DecompileConfiguration minecraftJars = minecraftProvider.getMinecraftJars(); + List minecraftJars = minecraftProvider.getMinecraftJarPaths(); assert minecraftJars.size() == 1; final File namedJar = minecraftJars.get(0).toFile(); diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessor.java index b1cf4299..34833a92 100644 --- a/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessor.java @@ -26,6 +26,7 @@ package net.fabricmc.loom.configuration.processors; import java.io.File; +@Deprecated(forRemoval = true) public interface JarProcessor { /** * Returns a unique ID for this jar processor, containing all configuration details. diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessorManager.java b/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessorManager.java deleted file mode 100644 index 1d602c30..00000000 --- a/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessorManager.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2016-2020 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.processors; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; -import java.util.jar.Attributes; -import java.util.jar.JarFile; -import java.util.jar.Manifest; -import java.util.stream.Collectors; - -import com.google.common.base.Preconditions; -import com.google.common.hash.Hashing; -import com.google.common.io.CharSource; - -import net.fabricmc.loom.util.ZipUtils; - -public class JarProcessorManager { - private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF"; - private static final String JAR_PROCESSOR_HASH_ATTRIBUTE = "Loom-Jar-Processor-Hash"; - private final List jarProcessors; - - public JarProcessorManager(List jarProcessors) { - this.jarProcessors = jarProcessors; - } - - public void setupProcessors() { - jarProcessors.forEach(JarProcessor::setup); - } - - public boolean active() { - return !jarProcessors.isEmpty(); - } - - public boolean isInvalid(File file) { - if (!file.exists()) { - return true; - } - - String jarProcessorHash = getJarProcessorHash(); - - try (JarFile jar = new JarFile(file)) { - Manifest manifest = jar.getManifest(); - - if (manifest == null) { - return false; - } - - Attributes attributes = manifest.getMainAttributes(); - - if (!jarProcessorHash.equals(attributes.getValue(JAR_PROCESSOR_HASH_ATTRIBUTE))) { - return true; - } - } catch (IOException e) { - throw new UncheckedIOException("Could not check jar manifest of " + file, e); - } - - return false; - } - - private String getJarProcessorHash() { - String jarProcessorIds = jarProcessors.stream() - .map(JarProcessor::getId) - .sorted() - .collect(Collectors.joining(";")); - - try { - return CharSource.wrap(jarProcessorIds) - .asByteSource(StandardCharsets.UTF_8) - .hash(Hashing.sha256()) - .toString(); - } catch (IOException e) { - throw new UncheckedIOException("Could not hash jar processor IDs", e); - } - } - - public void process(File file) { - for (JarProcessor jarProcessor : jarProcessors) { - jarProcessor.process(file); - } - - try { - int count = ZipUtils.transform(file.toPath(), Map.of(MANIFEST_PATH, bytes -> { - Manifest manifest = new Manifest(new ByteArrayInputStream(bytes)); - manifest.getMainAttributes().putValue(JAR_PROCESSOR_HASH_ATTRIBUTE, getJarProcessorHash()); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - manifest.write(out); - return out.toByteArray(); - })); - - Preconditions.checkState(count > 0, "Did not add data to jar manifest in " + file); - } catch (IOException e) { - throw new UncheckedIOException("Could not add data to jar manifest in " + file, e); - } - } - - public T getByType(Class tClass) { - //noinspection unchecked - return (T) jarProcessors.stream().filter(jarProcessor -> jarProcessor.getClass().equals(tClass)).findFirst().orElse(null); - } -} diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/LegacyJarProcessorWrapper.java b/src/main/java/net/fabricmc/loom/configuration/processors/LegacyJarProcessorWrapper.java new file mode 100644 index 00000000..98ab2033 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/processors/LegacyJarProcessorWrapper.java @@ -0,0 +1,65 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 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.processors; + +import java.io.IOException; +import java.nio.file.Path; + +import javax.inject.Inject; + +import org.gradle.api.Project; +import org.jetbrains.annotations.Nullable; + +import net.fabricmc.loom.api.processor.MinecraftJarProcessor; +import net.fabricmc.loom.api.processor.ProcessorContext; +import net.fabricmc.loom.api.processor.SpecContext; + +/** + * Wrapper around the deprecated API. + */ +public abstract class LegacyJarProcessorWrapper implements MinecraftJarProcessor { + private final JarProcessor delegate; + + @Inject + public LegacyJarProcessorWrapper(JarProcessor delegate) { + this.delegate = delegate; + } + + public abstract Project getProject(); + + @Override + public @Nullable LegacyJarProcessorWrapper.Spec buildSpec(SpecContext context) { + delegate.setup(); + return new Spec(delegate.getId()); + } + + @Override + public void processJar(Path jar, Spec spec, ProcessorContext context) throws IOException { + delegate.process(jar.toFile()); + } + + public record Spec(String cacheValue) implements MinecraftJarProcessor.Spec { + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftJarProcessorManager.java b/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftJarProcessorManager.java new file mode 100644 index 00000000..aed0d22c --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftJarProcessorManager.java @@ -0,0 +1,145 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 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.processors; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.jetbrains.annotations.Nullable; + +import net.fabricmc.loom.api.processor.MinecraftJarProcessor; +import net.fabricmc.loom.api.processor.ProcessorContext; +import net.fabricmc.loom.api.processor.SpecContext; +import net.fabricmc.loom.util.ZipUtils; +import net.fabricmc.mappingio.tree.MemoryMappingTree; + +public final class MinecraftJarProcessorManager { + private static final String CACHE_VALUE_FILE_PATH = "META-INF/Loom-Jar-Processor-Cache"; + + private final List> jarProcessors; + + private MinecraftJarProcessorManager(List> jarProcessors) { + this.jarProcessors = Collections.unmodifiableList(jarProcessors); + } + + @Nullable + public static MinecraftJarProcessorManager create(List> processors, SpecContext context) { + List> entries = new ArrayList<>(); + + for (MinecraftJarProcessor processor : processors) { + MinecraftJarProcessor.Spec spec = processor.buildSpec(context); + + if (spec != null) { + entries.add(new ProcessorEntry<>(processor, spec)); + } + } + + if (entries.isEmpty()) { + return null; + } + + return new MinecraftJarProcessorManager(entries); + } + + private String getCacheValue() { + return jarProcessors.stream() + .sorted(Comparator.comparing(ProcessorEntry::name)) + .map(ProcessorEntry::cacheValue) + .collect(Collectors.joining("::")); + } + + public boolean requiresProcessingJar(Path jar) { + Objects.requireNonNull(jar); + + if (Files.notExists(jar)) { + return true; + } + + byte[] existingCache; + + try { + existingCache = ZipUtils.unpackNullable(jar, CACHE_VALUE_FILE_PATH); + } catch (IOException e) { + throw new UncheckedIOException("Failed to unpack jar: " + jar, e); + } + + if (existingCache == null) { + return true; + } + + final String existingCacheValue = new String(existingCache, StandardCharsets.UTF_8); + return !existingCacheValue.equals(getCacheValue()); + } + + public void processJar(Path jar, ProcessorContext context) throws IOException { + for (ProcessorEntry entry : jarProcessors) { + try { + entry.processJar(jar, context); + } catch (IOException e) { + throw new IOException("Failed to process jar when running jar processor: %s".formatted(entry.name()), e); + } + } + + ZipUtils.add(jar, CACHE_VALUE_FILE_PATH, getCacheValue()); + } + + public void processMappings(MemoryMappingTree mappings, ProcessorContext context) { + for (ProcessorEntry entry : jarProcessors) { + entry.processMappings(mappings, context); + } + } + + record ProcessorEntry(S spec, MinecraftJarProcessor processor, @Nullable MinecraftJarProcessor.MappingsProcessor mappingsProcessor) { + @SuppressWarnings("unchecked") + ProcessorEntry(MinecraftJarProcessor processor, MinecraftJarProcessor.Spec spec) { + this((S) Objects.requireNonNull(spec), (MinecraftJarProcessor) processor, (MinecraftJarProcessor.MappingsProcessor) processor.processMappings()); + } + + private void processJar(Path jar, ProcessorContext context) throws IOException { + processor().processJar(jar, spec, context); + } + + private void processMappings(MemoryMappingTree mappings, ProcessorContext context) { + mappingsProcessor().transform(mappings, spec, context); + } + + private String name() { + return processor.getName(); + } + + private String cacheValue() { + return processor.getName() + ":" + spec.cacheValue(); + } + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/ProcessorContextImpl.java b/src/main/java/net/fabricmc/loom/configuration/processors/ProcessorContextImpl.java new file mode 100644 index 00000000..382a54c9 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/processors/ProcessorContextImpl.java @@ -0,0 +1,58 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 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.processors; + +import org.gradle.api.Project; + +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.api.processor.ProcessorContext; +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJar; +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration; + +public record ProcessorContextImpl(MinecraftJarConfiguration jarConfiguration, MinecraftJar minecraftJar) implements ProcessorContext { + public static ProcessorContext create(Project project, MinecraftJar minecraftJar) { + return new ProcessorContextImpl(LoomGradleExtension.get(project).getMinecraftJarConfiguration().get(), minecraftJar); + } + + @Override + public MinecraftJarConfiguration getJarConfiguration() { + return jarConfiguration; + } + + @Override + public boolean isMerged() { + return minecraftJar.isMerged(); + } + + @Override + public boolean includesClient() { + return minecraftJar.includesClient(); + } + + @Override + public boolean includesServer() { + return minecraftJar.includesServer(); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextImpl.java b/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextImpl.java new file mode 100644 index 00000000..f487a814 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextImpl.java @@ -0,0 +1,44 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 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.processors; + +import java.util.List; + +import net.fabricmc.loom.api.processor.SpecContext; +import net.fabricmc.loom.util.fmj.FabricModJson; + +public class SpecContextImpl implements SpecContext { + @Override + public List getModDependencies() { + // TODO + return null; + } + + @Override + public List getMods() { + // TODO + return null; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftJar.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftJar.java new file mode 100644 index 00000000..4e18410f --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftJar.java @@ -0,0 +1,80 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 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.nio.file.Path; +import java.util.Objects; + +public abstract sealed class MinecraftJar permits MinecraftJar.Merged, MinecraftJar.Common, MinecraftJar.ServerOnly, MinecraftJar.ClientOnly { + private final Path path; + private final boolean merged, client, server; + + protected MinecraftJar(Path path, boolean merged, boolean client, boolean server) { + this.path = Objects.requireNonNull(path); + this.merged = merged; + this.client = client; + this.server = server; + } + + public Path getPath() { + return path; + } + + public boolean isMerged() { + return merged; + } + + public boolean includesClient() { + return client; + } + + public boolean includesServer() { + return server; + } + + public static final class Merged extends MinecraftJar { + public Merged(Path path) { + super(path, true, true, true); + } + } + + public static final class Common extends MinecraftJar { + public Common(Path path) { + super(path, false, false, true); + } + } + + public static final class ServerOnly extends MinecraftJar { + public ServerOnly(Path path) { + super(path, false, false, true); + } + } + + public static final class ClientOnly extends MinecraftJar { + public ClientOnly(Path path) { + super(path, false, true, false); + } + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftJarConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftJarConfiguration.java index 48a4ca9c..c48102b2 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftJarConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftJarConfiguration.java @@ -33,7 +33,7 @@ import org.gradle.api.Project; import net.fabricmc.loom.configuration.decompile.DecompileConfiguration; import net.fabricmc.loom.configuration.decompile.SingleJarDecompileConfiguration; import net.fabricmc.loom.configuration.decompile.SplitDecompileConfiguration; -import net.fabricmc.loom.configuration.processors.JarProcessorManager; +import net.fabricmc.loom.configuration.processors.MinecraftJarProcessorManager; import net.fabricmc.loom.configuration.providers.minecraft.mapped.IntermediaryMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.mapped.NamedMinecraftProvider; @@ -76,7 +76,7 @@ public enum MinecraftJarConfiguration { private final Function minecraftProviderFunction; private final BiFunction> intermediaryMinecraftProviderBiFunction; private final BiFunction> namedMinecraftProviderBiFunction; - private final BiFunction, JarProcessorManager, ProcessedNamedMinecraftProvider> processedNamedMinecraftProviderBiFunction; + private final BiFunction, MinecraftJarProcessorManager, ProcessedNamedMinecraftProvider> processedNamedMinecraftProviderBiFunction; private final BiFunction> decompileConfigurationBiFunction; private final List supportedEnvironments; @@ -85,14 +85,14 @@ public enum MinecraftJarConfiguration { Function minecraftProviderFunction, BiFunction> intermediaryMinecraftProviderBiFunction, BiFunction namedMinecraftProviderBiFunction, - BiFunction> processedNamedMinecraftProviderBiFunction, + BiFunction> processedNamedMinecraftProviderBiFunction, BiFunction> decompileConfigurationBiFunction, List supportedEnvironments ) { this.minecraftProviderFunction = (Function) minecraftProviderFunction; this.intermediaryMinecraftProviderBiFunction = (BiFunction>) (Object) intermediaryMinecraftProviderBiFunction; this.namedMinecraftProviderBiFunction = (BiFunction>) namedMinecraftProviderBiFunction; - this.processedNamedMinecraftProviderBiFunction = (BiFunction, JarProcessorManager, ProcessedNamedMinecraftProvider>) (Object) processedNamedMinecraftProviderBiFunction; + this.processedNamedMinecraftProviderBiFunction = (BiFunction, MinecraftJarProcessorManager, ProcessedNamedMinecraftProvider>) (Object) processedNamedMinecraftProviderBiFunction; this.decompileConfigurationBiFunction = (BiFunction>) decompileConfigurationBiFunction; this.supportedEnvironments = supportedEnvironments; } @@ -109,7 +109,7 @@ public enum MinecraftJarConfiguration { return namedMinecraftProviderBiFunction; } - public BiFunction, JarProcessorManager, ProcessedNamedMinecraftProvider> getProcessedNamedMinecraftProviderBiFunction() { + public BiFunction, MinecraftJarProcessorManager, ProcessedNamedMinecraftProvider> getProcessedNamedMinecraftProviderBiFunction() { return processedNamedMinecraftProviderBiFunction; } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/SingleJarEnvType.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/SingleJarEnvType.java new file mode 100644 index 00000000..7063c166 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/SingleJarEnvType.java @@ -0,0 +1,43 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 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.nio.file.Path; +import java.util.function.Function; + +public enum SingleJarEnvType { + CLIENT(MinecraftJar.ClientOnly::new), + SERVER(MinecraftJar.ServerOnly::new); + + private final Function jarFunction; + + SingleJarEnvType(Function jarFunction) { + this.jarFunction = jarFunction; + } + + public Function getJar() { + return jarFunction; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/SingleJarMinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/SingleJarMinecraftProvider.java index 9baafd93..83743035 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/SingleJarMinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/SingleJarMinecraftProvider.java @@ -57,7 +57,7 @@ public final class SingleJarMinecraftProvider extends MinecraftProvider { protected void initFiles() { super.initFiles(); - minecraftEnvOnlyJar = path("minecraft-%s-only.jar".formatted(environment.name())); + minecraftEnvOnlyJar = path("minecraft-%s-only.jar".formatted(environment.type())); } @Override @@ -92,7 +92,7 @@ public final class SingleJarMinecraftProvider extends MinecraftProvider { } } catch (Exception e) { Files.deleteIfExists(minecraftEnvOnlyJar); - throw new RuntimeException("Failed to process %s only jar".formatted(environment.name()), e); + throw new RuntimeException("Failed to process %s only jar".formatted(environment.type()), e); } finally { if (remapper != null) { remapper.finish(); @@ -115,15 +115,15 @@ public final class SingleJarMinecraftProvider extends MinecraftProvider { } private interface Environment { - String name(); + SingleJarEnvType type(); Path getInputJar(SingleJarMinecraftProvider provider) throws Exception; } private static final class Server implements Environment { @Override - public String name() { - return "server"; + public SingleJarEnvType type() { + return SingleJarEnvType.SERVER; } @Override @@ -141,8 +141,8 @@ public final class SingleJarMinecraftProvider extends MinecraftProvider { private static final class Client implements Environment { @Override - public String name() { - return "client"; + public SingleJarEnvType type() { + return SingleJarEnvType.CLIENT; } @Override diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/IntermediaryMinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/IntermediaryMinecraftProvider.java index b6a56ee4..5dd9cbdb 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/IntermediaryMinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/IntermediaryMinecraftProvider.java @@ -32,6 +32,7 @@ import org.gradle.api.Project; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; +import net.fabricmc.loom.configuration.providers.minecraft.SingleJarEnvType; import net.fabricmc.loom.configuration.providers.minecraft.SingleJarMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.SplitMinecraftProvider; import net.fabricmc.loom.util.SidedClassVisitor; @@ -87,19 +88,19 @@ public abstract sealed class IntermediaryMinecraftProvider implements SingleJar { - private final String env; + private final SingleJarEnvType env; - private SingleJarImpl(Project project, SingleJarMinecraftProvider minecraftProvider, String env) { + private SingleJarImpl(Project project, SingleJarMinecraftProvider minecraftProvider, SingleJarEnvType env) { super(project, minecraftProvider); this.env = env; } public static SingleJarImpl server(Project project, SingleJarMinecraftProvider minecraftProvider) { - return new SingleJarImpl(project, minecraftProvider, "server"); + return new SingleJarImpl(project, minecraftProvider, SingleJarEnvType.SERVER); } public static SingleJarImpl client(Project project, SingleJarMinecraftProvider minecraftProvider) { - return new SingleJarImpl(project, minecraftProvider, "client"); + return new SingleJarImpl(project, minecraftProvider, SingleJarEnvType.CLIENT); } @Override @@ -110,7 +111,7 @@ public abstract sealed class IntermediaryMinecraftProvider getMinecraftJars(); + default List getMinecraftJarPaths() { + return getMinecraftJars().stream().map(MinecraftJar::getPath).toList(); + } + + List getMinecraftJars(); interface ProviderImpl extends MappedMinecraftProvider { Path getJar(String name); @@ -42,8 +49,8 @@ public interface MappedMinecraftProvider { } @Override - default List getMinecraftJars() { - return List.of(getMergedJar()); + default List getMinecraftJars() { + return List.of(new MinecraftJar.Merged(getMergedJar())); } } @@ -60,13 +67,13 @@ public interface MappedMinecraftProvider { } @Override - default List getMinecraftJars() { - return List.of(getCommonJar(), getClientOnlyJar()); + default List getMinecraftJars() { + return List.of(new MinecraftJar.Common(getCommonJar()), new MinecraftJar.ClientOnly(getClientOnlyJar())); } } interface SingleJar extends ProviderImpl { - String env(); + SingleJarEnvType env(); default String envName() { return "%sOnly".formatted(env()); @@ -77,8 +84,8 @@ public interface MappedMinecraftProvider { } @Override - default List getMinecraftJars() { - return List.of(getEnvOnlyJar()); + default List getMinecraftJars() { + return List.of(env().getJar().apply(getEnvOnlyJar())); } } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/NamedMinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/NamedMinecraftProvider.java index 9c9cdff7..a9643deb 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/NamedMinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/NamedMinecraftProvider.java @@ -32,6 +32,7 @@ import org.gradle.api.Project; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; +import net.fabricmc.loom.configuration.providers.minecraft.SingleJarEnvType; import net.fabricmc.loom.configuration.providers.minecraft.SingleJarMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.SplitMinecraftProvider; import net.fabricmc.loom.util.SidedClassVisitor; @@ -97,19 +98,19 @@ public abstract class NamedMinecraftProvider extend } public static final class SingleJarImpl extends NamedMinecraftProvider implements SingleJar { - private final String env; + private final SingleJarEnvType env; - private SingleJarImpl(Project project, SingleJarMinecraftProvider minecraftProvider, String env) { + private SingleJarImpl(Project project, SingleJarMinecraftProvider minecraftProvider, SingleJarEnvType env) { super(project, minecraftProvider); this.env = env; } public static SingleJarImpl server(Project project, SingleJarMinecraftProvider minecraftProvider) { - return new SingleJarImpl(project, minecraftProvider, "server"); + return new SingleJarImpl(project, minecraftProvider, SingleJarEnvType.SERVER); } public static SingleJarImpl client(Project project, SingleJarMinecraftProvider minecraftProvider) { - return new SingleJarImpl(project, minecraftProvider, "client"); + return new SingleJarImpl(project, minecraftProvider, SingleJarEnvType.CLIENT); } @Override @@ -125,7 +126,7 @@ public abstract class NamedMinecraftProvider extend } @Override - public String env() { + public SingleJarEnvType env() { return env; } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/ProcessedNamedMinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/ProcessedNamedMinecraftProvider.java index 579081ff..4e479b42 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/ProcessedNamedMinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/ProcessedNamedMinecraftProvider.java @@ -30,25 +30,29 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.List; +import java.util.Objects; import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.loom.configuration.processors.JarProcessorManager; +import net.fabricmc.loom.configuration.processors.MinecraftJarProcessorManager; +import net.fabricmc.loom.configuration.processors.ProcessorContextImpl; import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider; +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJar; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets; +import net.fabricmc.loom.configuration.providers.minecraft.SingleJarEnvType; import net.fabricmc.loom.configuration.providers.minecraft.SingleJarMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.SplitMinecraftProvider; public abstract class ProcessedNamedMinecraftProvider> extends NamedMinecraftProvider { private final P parentMinecraftProvider; - private final JarProcessorManager jarProcessorManager; + private final MinecraftJarProcessorManager jarProcessorManager; private final String projectMappedName; private final Path projectMappedDir; - public ProcessedNamedMinecraftProvider(P parentMinecraftProvide, JarProcessorManager jarProcessorManager) { + public ProcessedNamedMinecraftProvider(P parentMinecraftProvide, MinecraftJarProcessorManager jarProcessorManager) { super(parentMinecraftProvide.getProject(), parentMinecraftProvide.getMinecraftProvider()); this.parentMinecraftProvider = parentMinecraftProvide; - this.jarProcessorManager = jarProcessorManager; + this.jarProcessorManager = Objects.requireNonNull(jarProcessorManager); this.projectMappedName = "minecraft-project-%s-".formatted(getProject().getPath().replace(':', '@')); @@ -62,42 +66,49 @@ public abstract class ProcessedNamedMinecraftProvider inputJars = parentMinecraftProvider.getMinecraftJars(); - boolean requiresProcessing = extension.refreshDeps() || inputJars.stream() - .map(this::getProcessedPath) - .map(Path::toFile) - .anyMatch(jarProcessorManager::isInvalid); + boolean requiresProcessing = parentMinecraftProvider.getMinecraftJarPaths().stream() + .anyMatch(jarProcessorManager::requiresProcessingJar); if (requiresProcessing) { - try { - Files.createDirectories(projectMappedDir); - } catch (IOException e) { - throw new UncheckedIOException("Failed to create project mapped dir", e); - } - - for (Path inputJar : inputJars) { - final Path outputJar = getProcessedPath(inputJar); - deleteSimilarJars(outputJar); - - Files.copy(inputJar, outputJar, StandardCopyOption.REPLACE_EXISTING); - jarProcessorManager.process(outputJar.toFile()); - } + processJars(); } if (applyDependencies) { - final List dependencyTargets = parentMinecraftProvider.getDependencyTargets(); - - if (dependencyTargets.isEmpty()) { - return; - } - - MinecraftSourceSets.get(getProject()).applyDependencies( - (configuration, name) -> getProject().getDependencies().add(configuration, getDependencyNotation(name)), - dependencyTargets - ); + applyDependencies(); } } + private void processJars() throws IOException { + try { + Files.createDirectories(projectMappedDir); + } catch (IOException e) { + throw new UncheckedIOException("Failed to create project mapped dir", e); + } + + for (MinecraftJar minecraftJar : parentMinecraftProvider.getMinecraftJars()) { + Path inputJar = minecraftJar.getPath(); + final Path outputJar = getProcessedPath(inputJar); + deleteSimilarJars(outputJar); + + Files.copy(inputJar, outputJar, StandardCopyOption.REPLACE_EXISTING); + + jarProcessorManager.processJar(outputJar, ProcessorContextImpl.create(getProject(), minecraftJar)); + } + } + + private void applyDependencies() { + final List dependencyTargets = parentMinecraftProvider.getDependencyTargets(); + + if (dependencyTargets.isEmpty()) { + return; + } + + MinecraftSourceSets.get(getProject()).applyDependencies( + (configuration, name) -> getProject().getDependencies().add(configuration, getDependencyNotation(name)), + dependencyTargets + ); + } + private void deleteSimilarJars(Path jar) throws IOException { Files.deleteIfExists(jar); @@ -124,8 +135,8 @@ public abstract class ProcessedNamedMinecraftProvider getMinecraftJars() { - return getParentMinecraftProvider().getMinecraftJars().stream() + public List getMinecraftJarPaths() { + return getParentMinecraftProvider().getMinecraftJarPaths().stream() .map(this::getProcessedPath) .toList(); } @@ -139,7 +150,7 @@ public abstract class ProcessedNamedMinecraftProvider implements Merged { - public MergedImpl(NamedMinecraftProvider.MergedImpl parentMinecraftProvide, JarProcessorManager jarProcessorManager) { + public MergedImpl(NamedMinecraftProvider.MergedImpl parentMinecraftProvide, MinecraftJarProcessorManager jarProcessorManager) { super(parentMinecraftProvide, jarProcessorManager); } @@ -150,7 +161,7 @@ public abstract class ProcessedNamedMinecraftProvider implements Split { - public SplitImpl(NamedMinecraftProvider.SplitImpl parentMinecraftProvide, JarProcessorManager jarProcessorManager) { + public SplitImpl(NamedMinecraftProvider.SplitImpl parentMinecraftProvide, MinecraftJarProcessorManager jarProcessorManager) { super(parentMinecraftProvide, jarProcessorManager); } @@ -166,19 +177,19 @@ public abstract class ProcessedNamedMinecraftProvider implements SingleJar { - private final String env; + private final SingleJarEnvType env; - private SingleJarImpl(NamedMinecraftProvider.SingleJarImpl parentMinecraftProvide, JarProcessorManager jarProcessorManager, String env) { + private SingleJarImpl(NamedMinecraftProvider.SingleJarImpl parentMinecraftProvide, MinecraftJarProcessorManager jarProcessorManager, SingleJarEnvType env) { super(parentMinecraftProvide, jarProcessorManager); this.env = env; } - public static ProcessedNamedMinecraftProvider.SingleJarImpl server(NamedMinecraftProvider.SingleJarImpl parentMinecraftProvide, JarProcessorManager jarProcessorManager) { - return new ProcessedNamedMinecraftProvider.SingleJarImpl(parentMinecraftProvide, jarProcessorManager, "server"); + public static ProcessedNamedMinecraftProvider.SingleJarImpl server(NamedMinecraftProvider.SingleJarImpl parentMinecraftProvide, MinecraftJarProcessorManager jarProcessorManager) { + return new ProcessedNamedMinecraftProvider.SingleJarImpl(parentMinecraftProvide, jarProcessorManager, SingleJarEnvType.SERVER); } - public static ProcessedNamedMinecraftProvider.SingleJarImpl client(NamedMinecraftProvider.SingleJarImpl parentMinecraftProvide, JarProcessorManager jarProcessorManager) { - return new ProcessedNamedMinecraftProvider.SingleJarImpl(parentMinecraftProvide, jarProcessorManager, "client"); + public static ProcessedNamedMinecraftProvider.SingleJarImpl client(NamedMinecraftProvider.SingleJarImpl parentMinecraftProvide, MinecraftJarProcessorManager jarProcessorManager) { + return new ProcessedNamedMinecraftProvider.SingleJarImpl(parentMinecraftProvide, jarProcessorManager, SingleJarEnvType.CLIENT); } @Override @@ -187,7 +198,7 @@ public abstract class ProcessedNamedMinecraftProvider jarProcessors; protected final ConfigurableFileCollection log4jConfigs; protected final RegularFileProperty accessWidener; @@ -85,6 +88,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA private final NamedDomainObjectContainer decompilers; private final NamedDomainObjectContainer mods; private final NamedDomainObjectList remapConfigurations; + private final ListProperty> minecraftJarProcessors; // A common mistake with layered mappings is to call the wrong `officialMojangMappings` method, use this to keep track of when we are building a layered mapping spec. protected final ThreadLocal layeredSpecBuilderScope = ThreadLocal.withInitial(() -> false); @@ -116,6 +120,9 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA this.decompilers = project.getObjects().domainObjectContainer(DecompilerOptions.class); this.mods = project.getObjects().domainObjectContainer(ModSettings.class); this.remapConfigurations = project.getObjects().namedDomainObjectList(RemapConfigurationSettings.class); + //noinspection unchecked + this.minecraftJarProcessors = (ListProperty>) (Object) project.getObjects().listProperty(MinecraftJarProcessor.class); + this.minecraftJarProcessors.finalizeValueOnRead(); this.minecraftJarConfiguration = project.getObjects().property(MinecraftJarConfiguration.class).convention(MinecraftJarConfiguration.MERGED); this.minecraftJarConfiguration.finalizeValueOnRead(); @@ -166,9 +173,21 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA @Override public ListProperty getGameJarProcessors() { + getDeprecationHelper().replaceWithInLoom2_0("getGameJarProcessors", "getMinecraftJarProcessors"); return jarProcessors; } + @Override + public void addJarProcessor(JarProcessor processor) { + getDeprecationHelper().replaceWithInLoom2_0("addJarProcessor", "getMinecraftJarProcessors"); + getMinecraftJarProcessors().add(getProject().getObjects().newInstance(LegacyJarProcessorWrapper.class, processor)); + } + + @Override + public ListProperty> getMinecraftJarProcessors() { + return minecraftJarProcessors; + } + @Override public Dependency officialMojangMappings() { if (layeredSpecBuilderScope.get()) { diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java index a81a6d29..a54882a6 100644 --- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java @@ -43,7 +43,6 @@ import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.InstallerData; import net.fabricmc.loom.configuration.LoomDependencyManager; import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile; -import net.fabricmc.loom.configuration.processors.JarProcessorManager; import net.fabricmc.loom.configuration.providers.mappings.IntermediaryMappingsProvider; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; @@ -63,7 +62,6 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen private final List transitiveAccessWideners = new ArrayList<>(); private LoomDependencyManager dependencyManager; - private JarProcessorManager jarProcessorManager; private MinecraftProvider minecraftProvider; private MappingsProviderImpl mappingsProvider; private NamedMinecraftProvider namedMinecraftProvider; @@ -115,16 +113,6 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen return Objects.requireNonNull(dependencyManager, "Cannot get LoomDependencyManager before it has been setup"); } - @Override - public void setJarProcessorManager(JarProcessorManager jarProcessorManager) { - this.jarProcessorManager = jarProcessorManager; - } - - @Override - public JarProcessorManager getJarProcessorManager() { - return Objects.requireNonNull(jarProcessorManager, "Cannot get JarProcessorManager before it has been setup"); - } - @Override public MinecraftProvider getMinecraftProvider() { return Objects.requireNonNull(minecraftProvider, "Cannot get MinecraftProvider before it has been setup"); diff --git a/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java b/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java index d7b693db..cce8773d 100644 --- a/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java +++ b/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java @@ -31,8 +31,8 @@ import org.gradle.api.logging.LogLevel; import org.gradle.api.logging.configuration.WarningMode; public interface DeprecationHelper { - default void replaceWithInLoom0_12(String currentName, String newName) { - toBeRemovedIn(currentName, newName, "Loom 0.12"); + default void replaceWithInLoom2_0(String currentName, String newName) { + toBeRemovedIn(currentName, newName, "Loom 2.0"); } default void toBeRemovedIn(String currentName, String newName, String removalVersion) {