diff --git a/build.gradle b/build.gradle index 30a8d565..3c9647a5 100644 --- a/build.gradle +++ b/build.gradle @@ -72,6 +72,7 @@ dependencies { implementation ('net.fabricmc:tiny-mappings-parser:0.3.0+build.17') implementation 'net.fabricmc:access-widener:1.0.0' + implementation 'net.fabricmc:mapping-io:0.1.3' implementation ('net.fabricmc:lorenz-tiny:3.0.0') { transitive = false diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java index 8cfaf41c..c3232acb 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java +++ b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java @@ -67,8 +67,11 @@ import net.fabricmc.loom.configuration.providers.forge.ForgeUserdevProvider; import net.fabricmc.loom.configuration.providers.forge.McpConfigProvider; import net.fabricmc.loom.configuration.providers.forge.PatchProvider; import net.fabricmc.loom.configuration.providers.forge.SrgProvider; +import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext; +import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec; +import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder; +import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency; import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; -import net.fabricmc.loom.configuration.providers.mappings.MojangMappingsDependency; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; import net.fabricmc.loom.util.ModPlatform; import net.fabricmc.loom.util.function.LazyBool; @@ -217,7 +220,14 @@ public class LoomGradleExtension { } public Dependency officialMojangMappings() { - return new MojangMappingsDependency(project, this); + return layered(LayeredMappingSpecBuilder::officalMojangMappings); + } + + public Dependency layered(Action action) { + LayeredMappingSpecBuilder builder = new LayeredMappingSpecBuilder(this); + action.execute(builder); + LayeredMappingSpec builtSpec = builder.build(); + return new LayeredMappingsDependency(new GradleMappingContext(project, "layers_" + builtSpec.getVersion().replace("+", "_").replace(".", "_")), builtSpec, builtSpec.getVersion()); } public LoomGradleExtension(Project project) { diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java new file mode 100644 index 00000000..d9357014 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java @@ -0,0 +1,74 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings; + +import java.io.File; + +import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.logging.Logger; + +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.configuration.providers.MinecraftProvider; + +public class GradleMappingContext implements MappingContext { + private final Project project; + private final LoomGradleExtension extension; + private final String workingDirName; + + public GradleMappingContext(Project project, String workingDirName) { + this.project = project; + this.extension = project.getExtensions().getByType(LoomGradleExtension.class); + this.workingDirName = workingDirName; + } + + @Override + public File mavenFile(String mavenNotation) { + Configuration configuration = project.getConfigurations().detachedConfiguration(project.getDependencies().create(mavenNotation)); + return configuration.getSingleFile(); + } + + @Override + public MappingsProvider mappingsProvider() { + return extension.getMappingsProvider(); + } + + @Override + public MinecraftProvider minecraftProvider() { + return extension.getMinecraftProvider(); + } + + @Override + public File workingDirectory(String name) { + File tempDir = new File(mappingsProvider().getMappingsDir().toFile(), workingDirName); + tempDir.mkdirs(); + return new File(tempDir, name); + } + + @Override + public Logger getLogger() { + return project.getLogger(); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpec.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpec.java new file mode 100644 index 00000000..3604e9d9 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpec.java @@ -0,0 +1,65 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings; + +import java.util.List; +import java.util.Objects; + +public class LayeredMappingSpec { + private final List> layers; + + public LayeredMappingSpec(List> layers) { + this.layers = layers; + } + + public List> layers() { + return layers; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof LayeredMappingSpec)) return false; + LayeredMappingSpec that = (LayeredMappingSpec) o; + return Objects.equals(layers, that.layers); + } + + @Override + public int hashCode() { + return Objects.hash(layers); + } + + @Override + public String toString() { + return "LayeredMappingSpec{" + + "layers=" + layers + + '}'; + } + + public String getVersion() { + // TODO something better? + return String.format("layered+hash.%d", Math.abs(hashCode())); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpecBuilder.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpecBuilder.java new file mode 100644 index 00000000..4ad9613d --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpecBuilder.java @@ -0,0 +1,73 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.gradle.api.Action; +import org.jetbrains.annotations.Nullable; + +import net.fabricmc.loom.LoomGradleExtension; +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.parchment.ParchmentMappingsSpecBuilder; + +public class LayeredMappingSpecBuilder { + private final List> layers = new LinkedList<>(); + @Nullable + private final LoomGradleExtension extension; + + public LayeredMappingSpecBuilder(LoomGradleExtension extension) { + this.extension = extension; + } + + public LayeredMappingSpecBuilder officalMojangMappings() { + layers.add(new MojangMappingsSpec(() -> extension != null && extension.isSilentMojangMappingsLicenseEnabled())); + return this; + } + + public LayeredMappingSpecBuilder parchment(String mavenNotation) { + parchment(mavenNotation, parchmentMappingsSpecBuilder -> parchmentMappingsSpecBuilder.setRemovePrefix(true)); + return this; + } + + public LayeredMappingSpecBuilder parchment(String mavenNotation, Action action) { + ParchmentMappingsSpecBuilder builder = ParchmentMappingsSpecBuilder.builder(mavenNotation); + action.execute(builder); + layers.add(builder.build()); + return this; + } + + public LayeredMappingSpec build() { + List> builtLayers = new LinkedList<>(); + // Intermediary is always the base layer + builtLayers.add(new IntermediaryMappingsSpec()); + builtLayers.addAll(layers); + + return new LayeredMappingSpec(Collections.unmodifiableList(builtLayers)); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java new file mode 100644 index 00000000..efd11e75 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java @@ -0,0 +1,143 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings; + +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Objects; +import java.util.Set; + +import org.gradle.api.artifacts.Dependency; +import org.gradle.api.artifacts.SelfResolvingDependency; +import org.gradle.api.tasks.TaskDependency; +import org.zeroturnaround.zip.ByteSource; +import org.zeroturnaround.zip.ZipEntrySource; +import org.zeroturnaround.zip.ZipUtil; + +import net.fabricmc.loom.LoomGradlePlugin; +import net.fabricmc.mappingio.adapter.MappingDstNsReorder; +import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; +import net.fabricmc.mappingio.format.Tiny2Writer; +import net.fabricmc.mappingio.tree.MemoryMappingTree; + +public class LayeredMappingsDependency implements SelfResolvingDependency { + private static final String GROUP = "loom"; + private static final String MODULE = "mappings"; + + private final MappingContext mappingContext; + private final LayeredMappingSpec layeredMappingSpec; + private final String version; + + public LayeredMappingsDependency(MappingContext mappingContext, LayeredMappingSpec layeredMappingSpec, String version) { + this.mappingContext = mappingContext; + this.layeredMappingSpec = layeredMappingSpec; + this.version = version; + } + + @Override + public Set resolve() { + Path mappingsDir = mappingContext.mappingsProvider().getMappingsDir(); + Path mappingsFile = mappingsDir.resolve(String.format("%s.%s-%s.tiny", GROUP, MODULE, getVersion())); + + if (!Files.exists(mappingsFile) || LoomGradlePlugin.refreshDeps) { + try { + LayeredMappingsProcessor processor = new LayeredMappingsProcessor(layeredMappingSpec); + MemoryMappingTree mappings = processor.getMappings(mappingContext); + + try (Writer writer = new StringWriter()) { + Tiny2Writer tiny2Writer = new Tiny2Writer(writer, false); + + MappingDstNsReorder nsReorder = new MappingDstNsReorder(tiny2Writer, Collections.singletonList(MappingNamespace.NAMED.stringValue())); + MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(nsReorder, MappingNamespace.INTERMEDIARY.stringValue()); + mappings.accept(nsSwitch); + + Files.deleteIfExists(mappingsFile); + + ZipUtil.pack(new ZipEntrySource[] { + new ByteSource("mappings/mappings.tiny", writer.toString().getBytes(StandardCharsets.UTF_8)) + }, mappingsFile.toFile()); + } + } catch (IOException e) { + throw new RuntimeException("Failed to resolve Mojang mappings", e); + } + } + + return Collections.singleton(mappingsFile.toFile()); + } + + @Override + public Set resolve(boolean transitive) { + return resolve(); + } + + @Override + public TaskDependency getBuildDependencies() { + return task -> Collections.emptySet(); + } + + @Override + public String getGroup() { + return GROUP; + } + + @Override + public String getName() { + return MODULE; + } + + @Override + public String getVersion() { + return version; + } + + @Override + public boolean contentEquals(Dependency dependency) { + if (dependency instanceof LayeredMappingsDependency) { + return Objects.equals(dependency.getVersion(), this.getVersion()); + } + + return false; + } + + @Override + public Dependency copy() { + return new LayeredMappingsDependency(mappingContext, layeredMappingSpec, version); + } + + @Override + public String getReason() { + return null; + } + + @Override + public void because(String s) { + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsProcessor.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsProcessor.java new file mode 100644 index 00000000..5e3ff9a2 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsProcessor.java @@ -0,0 +1,89 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; +import net.fabricmc.mappingio.tree.MemoryMappingTree; + +public class LayeredMappingsProcessor { + private final LayeredMappingSpec layeredMappingSpec; + + public LayeredMappingsProcessor(LayeredMappingSpec spec) { + this.layeredMappingSpec = spec; + } + + public MemoryMappingTree getMappings(MappingContext context) throws IOException { + MemoryMappingTree mappingTree = new MemoryMappingTree(); + + List> visitedLayers = new ArrayList<>(); + + for (MappingsSpec spec : layeredMappingSpec.layers()) { + MappingLayer layer = spec.createLayer(context); + + for (Class dependentLayer : layer.dependsOn()) { + if (!visitedLayers.contains(dependentLayer)) { + throw new RuntimeException(String.format("Layer %s depends on %s", layer.getClass().getName(), dependentLayer.getName())); + } + } + + visitedLayers.add(layer.getClass()); + + // We have to rebuild a new tree to work on when a layer doesnt merge into layered + boolean rebuild = layer.getSourceNamespace() != MappingNamespace.NAMED; + MemoryMappingTree workingTree; + + if (rebuild) { + MemoryMappingTree tempTree = new MemoryMappingTree(); + + // This can be null on the first layer + if (mappingTree.getSrcNamespace() != null) { + MappingSourceNsSwitch sourceNsSwitch = new MappingSourceNsSwitch(tempTree, layer.getSourceNamespace().stringValue()); + mappingTree.accept(sourceNsSwitch); + } + + workingTree = tempTree; + } else { + workingTree = mappingTree; + } + + try { + layer.visit(workingTree); + } catch (IOException e) { + throw new IOException("Failed to visit: " + layer.getClass(), e); + } + + if (rebuild) { + mappingTree = new MemoryMappingTree(); + workingTree.accept(new MappingSourceNsSwitch(mappingTree, MappingNamespace.NAMED.stringValue())); + } + } + + return mappingTree; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingContext.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingContext.java new file mode 100644 index 00000000..0d2b5f20 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingContext.java @@ -0,0 +1,50 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings; + +import java.io.File; + +import org.gradle.api.logging.Logger; + +import net.fabricmc.loom.configuration.providers.MinecraftProvider; + +public interface MappingContext { + File mavenFile(String mavenNotation); + + MappingsProvider mappingsProvider(); + + MinecraftProvider minecraftProvider(); + + default String minecraftVersion() { + return minecraftProvider().getMinecraftVersion(); + } + + /** + * Creates a temporary working dir to be used to store working files. + */ + File workingDirectory(String name); + + Logger getLogger(); +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingLayer.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingLayer.java new file mode 100644 index 00000000..2fdd451f --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingLayer.java @@ -0,0 +1,43 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import net.fabricmc.mappingio.MappingVisitor; + +public interface MappingLayer { + void visit(MappingVisitor mappingVisitor) throws IOException; + + default MappingNamespace getSourceNamespace() { + return MappingNamespace.NAMED; + } + + default List> dependsOn() { + return Collections.emptyList(); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingNamespace.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingNamespace.java new file mode 100644 index 00000000..8ac400ad --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingNamespace.java @@ -0,0 +1,37 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings; + +import java.util.Locale; + +public enum MappingNamespace { + OFFICIAL, + INTERMEDIARY, + NAMED; + + public String stringValue() { + return name().toLowerCase(Locale.ROOT); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java index 1ef2d049..7c25b681 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java @@ -569,6 +569,14 @@ public class MappingsProvider extends DependencyProvider { return hasUnpickDefinitions; } + public File intermediaryTinyFile() { + try { + return getIntermediaryTiny().toFile(); + } catch (IOException e) { + throw new RuntimeException("Failed to get intermediary", e); + } + } + public static class UnpickMetadata { public final String unpickGroup; public final String unpickVersion; diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsSpec.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsSpec.java new file mode 100644 index 00000000..1666d95c --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsSpec.java @@ -0,0 +1,29 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings; + +public interface MappingsSpec { + L createLayer(MappingContext context); +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MojangMappingsDependency.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MojangMappingsDependency.java deleted file mode 100644 index 0b46830f..00000000 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MojangMappingsDependency.java +++ /dev/null @@ -1,343 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2016, 2017, 2018 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.mappings; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.StringWriter; -import java.io.UncheckedIOException; -import java.io.Writer; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collections; -import java.util.Set; -import java.util.function.Consumer; - -import org.cadixdev.lorenz.MappingSet; -import org.cadixdev.lorenz.io.TextMappingsWriter; -import org.cadixdev.lorenz.io.proguard.ProGuardReader; -import org.cadixdev.lorenz.model.ClassMapping; -import org.cadixdev.lorenz.model.FieldMapping; -import org.cadixdev.lorenz.model.InnerClassMapping; -import org.cadixdev.lorenz.model.MethodMapping; -import org.cadixdev.lorenz.model.TopLevelClassMapping; -import org.gradle.api.Action; -import org.gradle.api.Project; -import org.gradle.api.artifacts.Dependency; -import org.gradle.api.artifacts.ExternalModuleDependency; -import org.gradle.api.artifacts.ModuleIdentifier; -import org.gradle.api.artifacts.ModuleVersionIdentifier; -import org.gradle.api.artifacts.MutableVersionConstraint; -import org.gradle.api.artifacts.SelfResolvingDependency; -import org.gradle.api.artifacts.VersionConstraint; -import org.gradle.api.internal.artifacts.DefaultModuleIdentifier; -import org.gradle.api.internal.artifacts.ModuleVersionSelectorStrictSpec; -import org.gradle.api.internal.artifacts.dependencies.AbstractModuleDependency; -import org.gradle.api.internal.artifacts.dependencies.DefaultMutableVersionConstraint; -import org.gradle.api.tasks.TaskDependency; -import org.zeroturnaround.zip.ByteSource; -import org.zeroturnaround.zip.ZipEntrySource; -import org.zeroturnaround.zip.ZipUtil; - -import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.loom.LoomGradlePlugin; -import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; -import net.fabricmc.loom.util.HashedDownloadUtil; -import net.fabricmc.lorenztiny.TinyMappingsReader; -import net.fabricmc.mapping.tree.TinyMappingFactory; - -public class MojangMappingsDependency extends AbstractModuleDependency implements SelfResolvingDependency, ExternalModuleDependency { - public static final String GROUP = "net.minecraft"; - public static final String MODULE = "mappings"; - // Keys in dependency manifest - private static final String MANIFEST_CLIENT_MAPPINGS = "client_mappings"; - private static final String MANIFEST_SERVER_MAPPINGS = "server_mappings"; - - private final Project project; - private final LoomGradleExtension extension; - - private boolean changing; - private boolean force; - - public MojangMappingsDependency(Project project, LoomGradleExtension extension) { - super(null); - this.project = project; - this.extension = extension; - } - - @Override - public ExternalModuleDependency copy() { - MojangMappingsDependency copiedProjectDependency = new MojangMappingsDependency(project, extension); - this.copyTo(copiedProjectDependency); - return copiedProjectDependency; - } - - @Override - public void version(Action action) { - } - - @Override - public boolean isForce() { - return this.force; - } - - @Override - public ExternalModuleDependency setForce(boolean force) { - this.validateMutation(this.force, force); - this.force = force; - return this; - } - - @Override - public boolean isChanging() { - return this.changing; - } - - @Override - public ExternalModuleDependency setChanging(boolean changing) { - this.validateMutation(this.changing, changing); - this.changing = changing; - return this; - } - - @Override - public Set resolve() { - Path mappingsDir; - try { - mappingsDir = extension.getMappingsProvider().getMappedVersionedDir(String.format("mojang/%s.%s-%s", GROUP, MODULE, getVersion())); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - Path mappingsFile = mappingsDir.resolve("mappings.tiny"); - Path clientMappings = mappingsDir.resolve("client.map"); - Path serverMappings = mappingsDir.resolve("server.map"); - - if (!Files.exists(mappingsFile) || LoomGradlePlugin.refreshDeps) { - MappingSet mappingSet; - - try { - mappingSet = getMappingsSet(clientMappings, serverMappings); - - try (Writer writer = new StringWriter()) { - new TinyWriter(writer, "intermediary", "named").write(mappingSet); - Files.deleteIfExists(mappingsFile); - - ZipUtil.pack(new ZipEntrySource[] { - new ByteSource("mappings/mappings.tiny", writer.toString().getBytes(StandardCharsets.UTF_8)) - }, mappingsFile.toFile()); - } - } catch (IOException e) { - throw new RuntimeException("Failed to resolve Mojang mappings", e); - } - } - - if (!extension.isSilentMojangMappingsLicenseEnabled()) { - try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings, StandardCharsets.UTF_8)) { - project.getLogger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); - project.getLogger().warn("Using of the official minecraft mappings is at your own risk!"); - project.getLogger().warn("Please make sure to read and understand the following license:"); - project.getLogger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); - String line; - - while ((line = clientBufferedReader.readLine()).startsWith("#")) { - project.getLogger().warn(line); - } - - project.getLogger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); - } catch (IOException e) { - throw new RuntimeException("Failed to read client mappings", e); - } - } - - return Collections.singleton(mappingsFile.toFile()); - } - - private MappingSet getMappingsSet(Path clientMappings, Path serverMappings) throws IOException { - MinecraftVersionMeta versionInfo = extension.getMinecraftProvider().getVersionInfo(); - - if (versionInfo.getDownload(MANIFEST_CLIENT_MAPPINGS) == null) { - throw new RuntimeException("Failed to find official mojang mappings for " + getVersion()); - } - - MinecraftVersionMeta.Download clientMappingsDownload = versionInfo.getDownload(MANIFEST_CLIENT_MAPPINGS); - MinecraftVersionMeta.Download serverMappingsDownload = versionInfo.getDownload(MANIFEST_CLIENT_MAPPINGS); - - HashedDownloadUtil.downloadIfInvalid(new URL(clientMappingsDownload.getUrl()), clientMappings.toFile(), clientMappingsDownload.getSha1(), project.getLogger(), false); - HashedDownloadUtil.downloadIfInvalid(new URL(serverMappingsDownload.getUrl()), serverMappings.toFile(), clientMappingsDownload.getSha1(), project.getLogger(), false); - - MappingSet mappings = MappingSet.create(); - - try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings, StandardCharsets.UTF_8); - BufferedReader serverBufferedReader = Files.newBufferedReader(serverMappings, StandardCharsets.UTF_8)) { - try (ProGuardReader proGuardReaderClient = new ProGuardReader(clientBufferedReader); - ProGuardReader proGuardReaderServer = new ProGuardReader(serverBufferedReader)) { - proGuardReaderClient.read(mappings); - proGuardReaderServer.read(mappings); - } - } - - MappingSet officialToNamed = mappings.reverse(); - MappingSet intermediaryToOfficial; - - try (BufferedReader reader = Files.newBufferedReader(extension.getMappingsProvider().getIntermediaryTiny(), StandardCharsets.UTF_8)) { - intermediaryToOfficial = new TinyMappingsReader(TinyMappingFactory.loadWithDetection(reader), "intermediary", "official").read(); - } - - MappingSet intermediaryToMojang = MappingSet.create(); - - // Merging. Don't use MappingSet#merge - iterateClasses(intermediaryToOfficial, inputMappings -> { - officialToNamed.getClassMapping(inputMappings.getFullDeobfuscatedName()) - .ifPresent(namedClass -> { - ClassMapping mojangClassMapping = intermediaryToMojang.getOrCreateClassMapping(inputMappings.getFullObfuscatedName()) - .setDeobfuscatedName(namedClass.getFullDeobfuscatedName()); - - for (FieldMapping fieldMapping : inputMappings.getFieldMappings()) { - namedClass.getFieldMapping(fieldMapping.getDeobfuscatedName()) - .ifPresent(namedField -> { - mojangClassMapping.getOrCreateFieldMapping(fieldMapping.getSignature()) - .setDeobfuscatedName(namedField.getDeobfuscatedName()); - }); - } - - for (MethodMapping methodMapping : inputMappings.getMethodMappings()) { - namedClass.getMethodMapping(methodMapping.getDeobfuscatedSignature()) - .ifPresent(namedMethod -> { - mojangClassMapping.getOrCreateMethodMapping(methodMapping.getSignature()) - .setDeobfuscatedName(namedMethod.getDeobfuscatedName()); - }); - } - }); - }); - - return intermediaryToMojang; - } - - @Override - public Set resolve(boolean transitive) { - return resolve(); - } - - @Override - public TaskDependency getBuildDependencies() { - return task -> Collections.emptySet(); - } - - @Override - public String getGroup() { - return GROUP; - } - - @Override - public String getName() { - return MODULE; - } - - @Override - public String getVersion() { - if (extension.getDependencyManager() == null) return "1.0.0"; - return extension.getMinecraftProvider().getMinecraftVersion(); - } - - @Override - public VersionConstraint getVersionConstraint() { - return new DefaultMutableVersionConstraint(getVersion()); - } - - @Override - public boolean matchesStrictly(ModuleVersionIdentifier identifier) { - return (new ModuleVersionSelectorStrictSpec(this)).isSatisfiedBy(identifier); - } - - @Override - public ModuleIdentifier getModule() { - return DefaultModuleIdentifier.newId(GROUP, MODULE); - } - - @Override - public boolean contentEquals(Dependency dependency) { - if (dependency instanceof MojangMappingsDependency) { - return ((MojangMappingsDependency) dependency).extension.getMinecraftProvider().getMinecraftVersion().equals(getVersion()); - } - - return false; - } - - @Override - public String getReason() { - return null; - } - - @Override - public void because(String s) { - } - - private static void iterateClasses(MappingSet mappings, Consumer> consumer) { - for (TopLevelClassMapping classMapping : mappings.getTopLevelClassMappings()) { - iterateClass(classMapping, consumer); - } - } - - private static void iterateClass(ClassMapping classMapping, Consumer> consumer) { - consumer.accept(classMapping); - - for (InnerClassMapping innerClassMapping : classMapping.getInnerClassMappings()) { - iterateClass(innerClassMapping, consumer); - } - } - - private static class TinyWriter extends TextMappingsWriter { - private final String namespaceFrom; - private final String namespaceTo; - - protected TinyWriter(Writer writer, String namespaceFrom, String namespaceTo) { - super(writer); - this.namespaceFrom = namespaceFrom; - this.namespaceTo = namespaceTo; - } - - @Override - public void write(MappingSet mappings) { - writer.println("tiny\t2\t0\t" + namespaceFrom + "\t" + namespaceTo); - - iterateClasses(mappings, classMapping -> { - writer.println("c\t" + classMapping.getFullObfuscatedName() + "\t" + classMapping.getFullDeobfuscatedName()); - - for (FieldMapping fieldMapping : classMapping.getFieldMappings()) { - fieldMapping.getType().ifPresent(fieldType -> { - writer.println("\tf\t" + fieldType + "\t" + fieldMapping.getObfuscatedName() + "\t" + fieldMapping.getDeobfuscatedName()); - }); - } - - for (MethodMapping methodMapping : classMapping.getMethodMappings()) { - writer.println("\tm\t" + methodMapping.getSignature().getDescriptor() + "\t" + methodMapping.getObfuscatedName() + "\t" + methodMapping.getDeobfuscatedName()); - } - }); - } - } -} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/intermediary/IntermediaryMappingLayer.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/intermediary/IntermediaryMappingLayer.java new file mode 100644 index 00000000..50da325c --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/intermediary/IntermediaryMappingLayer.java @@ -0,0 +1,84 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings.intermediary; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.Collections; +import java.util.Objects; + +import net.fabricmc.loom.configuration.providers.mappings.MappingLayer; +import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace; +import net.fabricmc.mappingio.MappingVisitor; +import net.fabricmc.mappingio.adapter.MappingNsCompleter; +import net.fabricmc.mappingio.format.Tiny2Reader; + +public class IntermediaryMappingLayer implements MappingLayer { + private final File tinyFile; + + public IntermediaryMappingLayer(File tinyFile) { + this.tinyFile = tinyFile; + } + + public File tinyFile() { + return tinyFile; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + IntermediaryMappingLayer that = (IntermediaryMappingLayer) obj; + return Objects.equals(this.tinyFile, that.tinyFile); + } + + @Override + public int hashCode() { + return Objects.hash(tinyFile); + } + + @Override + public String toString() { + return "IntermediaryMappingLayer[tinyFile=" + tinyFile + ']'; + } + + @Override + public MappingNamespace getSourceNamespace() { + return MappingNamespace.OFFICIAL; + } + + @Override + public void visit(MappingVisitor mappingVisitor) throws IOException { + // Populate named with intermediary and add Add a "named" namespace + MappingNsCompleter nsCompleter = new MappingNsCompleter(mappingVisitor, Collections.singletonMap(MappingNamespace.NAMED.stringValue(), MappingNamespace.INTERMEDIARY.stringValue()), true); + + try (BufferedReader reader = Files.newBufferedReader(tinyFile().toPath(), StandardCharsets.UTF_8)) { + Tiny2Reader.read(reader, nsCompleter); + } + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/intermediary/IntermediaryMappingsSpec.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/intermediary/IntermediaryMappingsSpec.java new file mode 100644 index 00000000..569c2357 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/intermediary/IntermediaryMappingsSpec.java @@ -0,0 +1,53 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings.intermediary; + +import net.fabricmc.loom.configuration.providers.mappings.MappingContext; +import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec; + +public class IntermediaryMappingsSpec implements MappingsSpec { + public IntermediaryMappingsSpec() { + } + + @Override + public boolean equals(Object obj) { + return obj == this || obj != null && obj.getClass() == this.getClass(); + } + + @Override + public int hashCode() { + return 1; + } + + @Override + public String toString() { + return "IntermediaryMappingsSpec[]"; + } + + @Override + public IntermediaryMappingLayer createLayer(MappingContext context) { + return new IntermediaryMappingLayer(context.mappingsProvider().intermediaryTinyFile()); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingLayer.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingLayer.java new file mode 100644 index 00000000..f3d98f3c --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingLayer.java @@ -0,0 +1,163 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings.mojmap; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.function.BooleanSupplier; + +import org.gradle.api.logging.Logger; + +import net.fabricmc.loom.configuration.providers.mappings.MappingLayer; +import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace; +import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingLayer; +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; +import net.fabricmc.loom.util.HashedDownloadUtil; +import net.fabricmc.mappingio.MappingVisitor; +import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; +import net.fabricmc.mappingio.format.ProGuardReader; + +public class MojangMappingLayer implements MappingLayer { + private final MinecraftVersionMeta.Download clientDownload; + private final MinecraftVersionMeta.Download serverDownload; + private final File workingDir; + private final Logger logger; + private final BooleanSupplier silenceLicense; + + public MojangMappingLayer(MinecraftVersionMeta.Download clientDownload, + MinecraftVersionMeta.Download serverDownload, + File workingDir, + Logger logger, + BooleanSupplier silenceLicense) { + this.clientDownload = clientDownload; + this.serverDownload = serverDownload; + this.workingDir = workingDir; + this.logger = logger; + this.silenceLicense = silenceLicense; + } + + public MinecraftVersionMeta.Download clientDownload() { + return clientDownload; + } + + public MinecraftVersionMeta.Download serverDownload() { + return serverDownload; + } + + public File workingDir() { + return workingDir; + } + + public Logger logger() { + return logger; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + MojangMappingLayer that = (MojangMappingLayer) obj; + return Objects.equals(this.clientDownload, that.clientDownload) + && Objects.equals(this.serverDownload, that.serverDownload) + && Objects.equals(this.workingDir, that.workingDir) + && Objects.equals(this.logger, that.logger); + } + + @Override + public int hashCode() { + return Objects.hash(clientDownload, serverDownload, workingDir, logger); + } + + @Override + public String toString() { + return "MojangMappingLayer[" + + "clientDownload=" + clientDownload + ", " + + "serverDownload=" + serverDownload + ", " + + "workingDir=" + workingDir + ", " + + "logger=" + logger + ']'; + } + + @Override + public void visit(MappingVisitor mappingVisitor) throws IOException { + File clientMappings = new File(workingDir(), "client.txt"); + File serverMappings = new File(workingDir(), "server.txt"); + + download(clientMappings, serverMappings); + + if (!silenceLicense.getAsBoolean()) { + printMappingsLicense(clientMappings.toPath()); + } + + // Make official the source namespace + MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(mappingVisitor, MappingNamespace.OFFICIAL.stringValue()); + + try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings.toPath(), StandardCharsets.UTF_8); + BufferedReader serverBufferedReader = Files.newBufferedReader(serverMappings.toPath(), StandardCharsets.UTF_8)) { + ProGuardReader.read(clientBufferedReader, MappingNamespace.NAMED.stringValue(), MappingNamespace.OFFICIAL.stringValue(), nsSwitch); + ProGuardReader.read(serverBufferedReader, MappingNamespace.NAMED.stringValue(), MappingNamespace.OFFICIAL.stringValue(), nsSwitch); + } + } + + private void download(File clientMappings, File serverMappings) throws IOException { + HashedDownloadUtil.downloadIfInvalid(new URL(clientDownload().getUrl()), clientMappings, clientDownload().getSha1(), logger(), false); + HashedDownloadUtil.downloadIfInvalid(new URL(serverDownload().getUrl()), serverMappings, serverDownload().getSha1(), logger(), false); + } + + private void printMappingsLicense(Path clientMappings) { + try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings, StandardCharsets.UTF_8)) { + logger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + logger().warn("Using of the official minecraft mappings is at your own risk!"); + logger().warn("Please make sure to read and understand the following license:"); + logger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + String line; + + while ((line = clientBufferedReader.readLine()).startsWith("#")) { + logger().warn(line); + } + + logger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + } catch (IOException e) { + throw new RuntimeException("Failed to read client mappings", e); + } + } + + @Override + public MappingNamespace getSourceNamespace() { + return MappingNamespace.OFFICIAL; + } + + @Override + public List> dependsOn() { + return Collections.singletonList(IntermediaryMappingLayer.class); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingsSpec.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingsSpec.java new file mode 100644 index 00000000..58289da7 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingsSpec.java @@ -0,0 +1,79 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings.mojmap; + +import java.util.function.BooleanSupplier; + +import net.fabricmc.loom.configuration.providers.mappings.MappingContext; +import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec; +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; + +public class MojangMappingsSpec implements MappingsSpec { + private final BooleanSupplier silenceLicense; + + public MojangMappingsSpec(BooleanSupplier silenceLicense) { + this.silenceLicense = silenceLicense; + } + + public MojangMappingsSpec() { + this(() -> false); + } + + @Override + public boolean equals(Object obj) { + return obj == this || obj != null && obj.getClass() == this.getClass(); + } + + @Override + public int hashCode() { + return 1; + } + + @Override + public String toString() { + return "MojangMappingsSpec[]"; + } + + // Keys in dependency manifest + private static final String MANIFEST_CLIENT_MAPPINGS = "client_mappings"; + private static final String MANIFEST_SERVER_MAPPINGS = "server_mappings"; + + @Override + public MojangMappingLayer createLayer(MappingContext context) { + MinecraftVersionMeta versionInfo = context.minecraftProvider().getVersionInfo(); + + if (versionInfo.getDownload(MANIFEST_CLIENT_MAPPINGS) == null) { + throw new RuntimeException("Failed to find official mojang mappings for " + context.minecraftVersion()); + } + + return new MojangMappingLayer( + versionInfo.getDownload(MANIFEST_CLIENT_MAPPINGS), + versionInfo.getDownload(MANIFEST_SERVER_MAPPINGS), + context.workingDirectory("mojang"), + context.getLogger(), + silenceLicense + ); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingLayer.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingLayer.java new file mode 100644 index 00000000..4e263615 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingLayer.java @@ -0,0 +1,100 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings.parchment; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Objects; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import net.fabricmc.loom.LoomGradlePlugin; +import net.fabricmc.loom.configuration.providers.mappings.MappingLayer; +import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace; +import net.fabricmc.mappingio.MappingVisitor; + +public class ParchmentMappingLayer implements MappingLayer { + private final File parchmentFile; + private final boolean removePrefix; + + public ParchmentMappingLayer(File parchmentFile, boolean removePrefix) { + this.parchmentFile = parchmentFile; + this.removePrefix = removePrefix; + } + + public File parchmentFile() { + return parchmentFile; + } + + public boolean removePrefix() { + return removePrefix; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + ParchmentMappingLayer that = (ParchmentMappingLayer) obj; + return Objects.equals(this.parchmentFile, that.parchmentFile) + && this.removePrefix == that.removePrefix; + } + + @Override + public int hashCode() { + return Objects.hash(parchmentFile, removePrefix); + } + + @Override + public String toString() { + return "ParchmentMappingLayer[" + + "parchmentFile=" + parchmentFile + ", " + + "removePrefix=" + removePrefix + ']'; + } + + private static final String PARCHMENT_DATA_FILE_NAME = "parchment.json"; + + @Override + public void visit(MappingVisitor mappingVisitor) throws IOException { + ParchmentTreeV1 parchmentData = getParchmentData(); + + if (removePrefix()) { + mappingVisitor = new ParchmentPrefixStripingMappingVisitor(mappingVisitor); + } + + parchmentData.visit(mappingVisitor, MappingNamespace.NAMED.stringValue()); + } + + private ParchmentTreeV1 getParchmentData() throws IOException { + try (ZipFile zipFile = new ZipFile(parchmentFile())) { + ZipEntry zipFileEntry = zipFile.getEntry(PARCHMENT_DATA_FILE_NAME); + Objects.requireNonNull(zipFileEntry, String.format("Could not find %s in parchment data file", PARCHMENT_DATA_FILE_NAME)); + + try (InputStreamReader reader = new InputStreamReader(zipFile.getInputStream(zipFileEntry))) { + return LoomGradlePlugin.GSON.fromJson(reader, ParchmentTreeV1.class); + } + } + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingsSpec.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingsSpec.java new file mode 100644 index 00000000..9edd81e9 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingsSpec.java @@ -0,0 +1,74 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings.parchment; + +import java.util.Objects; + +import net.fabricmc.loom.configuration.providers.mappings.MappingContext; +import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec; + +public class ParchmentMappingsSpec implements MappingsSpec { + private final String mavenNotation; + private final boolean removePrefix; + + public ParchmentMappingsSpec(String mavenNotation, boolean removePrefix) { + this.mavenNotation = mavenNotation; + this.removePrefix = removePrefix; + } + + public String mavenNotation() { + return mavenNotation; + } + + public boolean removePrefix() { + return removePrefix; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + ParchmentMappingsSpec that = (ParchmentMappingsSpec) obj; + return Objects.equals(this.mavenNotation, that.mavenNotation) + && this.removePrefix == that.removePrefix; + } + + @Override + public int hashCode() { + return Objects.hash(mavenNotation, removePrefix); + } + + @Override + public String toString() { + return "ParchmentMappingsSpec[" + + "mavenNotation=" + mavenNotation + ", " + + "removePrefix=" + removePrefix + ']'; + } + + @Override + public ParchmentMappingLayer createLayer(MappingContext context) { + return new ParchmentMappingLayer(context.mavenFile(mavenNotation()), removePrefix()); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingsSpecBuilder.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingsSpecBuilder.java new file mode 100644 index 00000000..808e077c --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingsSpecBuilder.java @@ -0,0 +1,48 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings.parchment; + +public class ParchmentMappingsSpecBuilder { + private final String mavenNotation; + + private boolean removePrefix; + + private ParchmentMappingsSpecBuilder(String mavenNotation) { + this.mavenNotation = mavenNotation; + } + + public static ParchmentMappingsSpecBuilder builder(String depNotation) { + return new ParchmentMappingsSpecBuilder(depNotation); + } + + public ParchmentMappingsSpecBuilder setRemovePrefix(boolean removePrefix) { + this.removePrefix = removePrefix; + return this; + } + + public ParchmentMappingsSpec build() { + return new ParchmentMappingsSpec(mavenNotation, removePrefix); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentPrefixStripingMappingVisitor.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentPrefixStripingMappingVisitor.java new file mode 100644 index 00000000..6280a5f0 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentPrefixStripingMappingVisitor.java @@ -0,0 +1,50 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings.parchment; + +import java.util.Locale; + +import net.fabricmc.mappingio.MappingVisitor; +import net.fabricmc.mappingio.adapter.ForwardingMappingVisitor; + +public final class ParchmentPrefixStripingMappingVisitor extends ForwardingMappingVisitor { + protected ParchmentPrefixStripingMappingVisitor(MappingVisitor next) { + super(next); + } + + @Override + public boolean visitMethodArg(int argPosition, int lvIndex, String srcName) { + return super.visitMethodArg(argPosition, lvIndex, stripMethodArg(srcName)); + } + + public static String stripMethodArg(String arg) { + if (arg.length() > 1 && arg.startsWith("p") && Character.isUpperCase(arg.charAt(1))) { + String a2 = arg.substring(1); // Remove p + return a2.substring(0, 1).toLowerCase(Locale.ROOT) + a2.substring(1); // Make first char lowercase + } + + return arg; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentTreeV1.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentTreeV1.java new file mode 100644 index 00000000..0512578d --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentTreeV1.java @@ -0,0 +1,373 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.mappings.parchment; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import org.jetbrains.annotations.Nullable; + +import net.fabricmc.mappingio.MappedElementKind; +import net.fabricmc.mappingio.MappingVisitor; + +public final class ParchmentTreeV1 { + private final String version; + private final List classes; + private final List packages; + + ParchmentTreeV1(String version, List classes, List packages) { + this.version = version; + this.classes = classes; + this.packages = packages; + } + + public String version() { + return version; + } + + public List classes() { + return classes; + } + + public List packages() { + return packages; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + ParchmentTreeV1 that = (ParchmentTreeV1) obj; + return Objects.equals(this.version, that.version) + && Objects.equals(this.classes, that.classes) + && Objects.equals(this.packages, that.packages); + } + + @Override + public int hashCode() { + return Objects.hash(version, classes, packages); + } + + @Override + public String toString() { + return "ParchmentTreeV1[" + + "version=" + version + ", " + + "classes=" + classes + ", " + + "packages=" + packages + ']'; + } + + public void visit(MappingVisitor visitor, String srcNamespace) { + while (true) { + if (visitor.visitHeader()) { + visitor.visitNamespaces(srcNamespace, Collections.emptyList()); + } + + if (visitor.visitContent()) { + if (classes() != null) { + for (Class c : classes()) { + c.visit(visitor); + } + } + } + + if (visitor.visitEnd()) { + break; + } + } + } + + public static class Class { + private final String name; + @Nullable + private final List fields; + @Nullable + private final List methods; + @Nullable + private final List javadoc; + + public Class(String name, @Nullable List fields, @Nullable List methods, @Nullable List javadoc) { + this.name = name; + this.fields = fields; + this.methods = methods; + this.javadoc = javadoc; + } + + public String name() { + return name; + } + + public List fields() { + return fields; + } + + public List methods() { + return methods; + } + + public List javadoc() { + return javadoc; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Class)) return false; + Class aClass = (Class) o; + return Objects.equals(name, aClass.name) && Objects.equals(fields, aClass.fields) && Objects.equals(methods, aClass.methods) && Objects.equals(javadoc, aClass.javadoc); + } + + @Override + public int hashCode() { + return Objects.hash(name, fields, methods, javadoc); + } + + public void visit(MappingVisitor visitor) { + if (visitor.visitClass(name())) { + if (!visitor.visitElementContent(MappedElementKind.CLASS)) { + return; + } + + if (fields() != null) { + for (Field field : fields()) { + field.visit(visitor); + } + } + + if (methods() != null) { + for (Method method : methods()) { + method.visit(visitor); + } + } + + if (javadoc() != null) { + visitor.visitComment(MappedElementKind.CLASS, String.join("\n", javadoc())); + } + } + } + } + + public static class Field { + private final String name; + private final String descriptor; + @Nullable + private final List javadoc; + + public Field(String name, String descriptor, @Nullable List javadoc) { + this.name = name; + this.descriptor = descriptor; + this.javadoc = javadoc; + } + + public String name() { + return name; + } + + public String descriptor() { + return descriptor; + } + + public List javadoc() { + return javadoc; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Field)) return false; + Field field = (Field) o; + return Objects.equals(name, field.name) && Objects.equals(descriptor, field.descriptor) && Objects.equals(javadoc, field.javadoc); + } + + @Override + public int hashCode() { + return Objects.hash(name, descriptor, javadoc); + } + + public void visit(MappingVisitor visitor) { + if (visitor.visitField(name, descriptor)) { + if (!visitor.visitElementContent(MappedElementKind.FIELD)) { + return; + } + + if (javadoc() != null) { + visitor.visitComment(MappedElementKind.FIELD, String.join("\n", javadoc())); + } + } + } + } + + public static class Method { + private final String name; + private final String descriptor; + @Nullable + private final List parameters; + @Nullable + private final List javadoc; + + public Method(String name, String descriptor, @Nullable List parameters, @Nullable List javadoc) { + this.name = name; + this.descriptor = descriptor; + this.parameters = parameters; + this.javadoc = javadoc; + } + + public String name() { + return name; + } + + public String descriptor() { + return descriptor; + } + + public List parameters() { + return parameters; + } + + public List javadoc() { + return javadoc; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Method)) return false; + Method method = (Method) o; + return Objects.equals(name, method.name) && Objects.equals(descriptor, method.descriptor) && Objects.equals(parameters, method.parameters) && Objects.equals(javadoc, method.javadoc); + } + + @Override + public int hashCode() { + return Objects.hash(name, descriptor, parameters, javadoc); + } + + public void visit(MappingVisitor visitor) { + if (visitor.visitMethod(name, descriptor)) { + if (!visitor.visitElementContent(MappedElementKind.METHOD)) { + return; + } + + if (parameters() != null) { + for (Parameter parameter : parameters()) { + parameter.visit(visitor); + } + } + + if (javadoc() != null) { + visitor.visitComment(MappedElementKind.METHOD, String.join("\n", javadoc())); + } + } + } + } + + public static class Parameter { + private final int index; + private final String name; + @Nullable + private final String javadoc; + + public Parameter(int index, String name, @Nullable String javadoc) { + this.index = index; + this.name = name; + this.javadoc = javadoc; + } + + public int index() { + return index; + } + + public String name() { + return name; + } + + public String javadoc() { + return javadoc; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Parameter)) return false; + Parameter parameter = (Parameter) o; + return index == parameter.index && Objects.equals(name, parameter.name) && Objects.equals(javadoc, parameter.javadoc); + } + + @Override + public int hashCode() { + return Objects.hash(index, name, javadoc); + } + + public void visit(MappingVisitor visitor) { + if (visitor.visitMethodArg(index, index, name)) { + if (!visitor.visitElementContent(MappedElementKind.METHOD_ARG)) { + return; + } + + if (javadoc() != null) { + visitor.visitComment(MappedElementKind.METHOD_ARG, javadoc); + } + } + } + } + + public static class Package { + private final String name; + private final List javadoc; + + public Package(String name, List javadoc) { + this.name = name; + this.javadoc = javadoc; + } + + public String name() { + return name; + } + + public List javadoc() { + return javadoc; + } + + @Override + public String toString() { + return "Package{" + + "name='" + name + '\'' + + ", javadoc=" + javadoc + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Package)) return false; + Package aPackage = (Package) o; + return Objects.equals(name, aPackage.name) && Objects.equals(javadoc, aPackage.javadoc); + } + + @Override + public int hashCode() { + return Objects.hash(name, javadoc); + } + } +} diff --git a/src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java b/src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java index f033b0f3..0dbd7e19 100644 --- a/src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java +++ b/src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java @@ -49,8 +49,9 @@ import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.options.Option; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder; +import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency; import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; -import net.fabricmc.loom.configuration.providers.mappings.MojangMappingsDependency; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; import net.fabricmc.loom.util.SourceRemapper; import net.fabricmc.lorenztiny.TinyMappingsJoiner; @@ -118,12 +119,13 @@ public class MigrateMappingsTask extends AbstractLoomTask { Set files; try { - if (mappings.startsWith(MojangMappingsDependency.GROUP + ':' + MojangMappingsDependency.MODULE + ':') || mappings.startsWith("net.mojang.minecraft:mappings:")) { + if (mappings.startsWith("net.minecraft:mappings:") || mappings.startsWith("net.mojang.minecraft:mappings:")) { if (!mappings.endsWith(":" + project.getExtensions().getByType(LoomGradleExtension.class).getMinecraftProvider().getMinecraftVersion())) { throw new UnsupportedOperationException("Migrating Mojang mappings is currently only supported for the specified minecraft version"); } - files = new MojangMappingsDependency(project, getExtension()).resolve(); + LayeredMappingsDependency dep = (LayeredMappingsDependency) getExtension().layered(LayeredMappingSpecBuilder::officalMojangMappings); + files = dep.resolve(); } else { Dependency dependency = project.getDependencies().create(mappings); files = project.getConfigurations().detachedConfiguration(dependency).resolve();