aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.gradle21
-rw-r--r--src/forgeInject/java/net/fabricmc/loom/inject/Pair.java52
-rw-r--r--src/forgeInject/java/net/fabricmc/loom/inject/YarnNamingService.java126
-rw-r--r--src/forgeInject/resources/META-INF/services/cpw.mods.modlauncher.api.INameMappingService1
-rw-r--r--src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java42
5 files changed, 226 insertions, 16 deletions
diff --git a/build.gradle b/build.gradle
index 18e33cab..ec7bacfe 100644
--- a/build.gradle
+++ b/build.gradle
@@ -24,6 +24,10 @@ if (ENV.BUILD_NUMBER) {
version = baseVersion + '-forge.28'
}
+sourceSets {
+ forgeInject
+}
+
repositories {
maven {
name = 'Fabric'
@@ -79,6 +83,10 @@ dependencies {
implementation ('org.cadixdev:atlas:0.2.0')
implementation ('net.minecraftforge.gradle:ForgeGradle:3.0.179')
+ // Forge injection
+ forgeInjectImplementation ('net.fabricmc:tiny-mappings-parser:0.2.2.14') // TODO: Shade this
+ forgeInjectImplementation ('cpw.mods:modlauncher:6.1.3')
+
// Testing
testImplementation(gradleTestKit())
testImplementation('org.spockframework:spock-core:1.3-groovy-2.4') {
@@ -86,7 +94,20 @@ dependencies {
}
}
+task forgeInjectJar(type: Jar, dependsOn: [compileForgeInjectJava, processForgeInjectResources]) {
+ classifier = 'forgeinject'
+ from compileForgeInjectJava.outputs
+ from processForgeInjectResources.outputs
+}
+
jar {
+ dependsOn forgeInjectJar
+
+ from(forgeInjectJar.outputs) {
+ into "inject"
+ rename { "injection.jar" }
+ }
+
manifest {
attributes 'Implementation-Version': version + ' Build(' + build + ')'
}
diff --git a/src/forgeInject/java/net/fabricmc/loom/inject/Pair.java b/src/forgeInject/java/net/fabricmc/loom/inject/Pair.java
new file mode 100644
index 00000000..0206cb5d
--- /dev/null
+++ b/src/forgeInject/java/net/fabricmc/loom/inject/Pair.java
@@ -0,0 +1,52 @@
+/*
+ * 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.inject;
+
+import java.util.Map;
+
+final class Pair<A, B> implements Map.Entry<A, B> {
+ private final A first;
+ private final B second;
+
+ Pair(A first, B second) {
+ this.first = first;
+ this.second = second;
+ }
+
+ @Override
+ public A getKey() {
+ return first;
+ }
+
+ @Override
+ public B getValue() {
+ return second;
+ }
+
+ @Override
+ public B setValue(B value) {
+ throw new UnsupportedOperationException("Pairs are immutable!");
+ }
+}
diff --git a/src/forgeInject/java/net/fabricmc/loom/inject/YarnNamingService.java b/src/forgeInject/java/net/fabricmc/loom/inject/YarnNamingService.java
new file mode 100644
index 00000000..c9de6ed4
--- /dev/null
+++ b/src/forgeInject/java/net/fabricmc/loom/inject/YarnNamingService.java
@@ -0,0 +1,126 @@
+/*
+ * 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.inject;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.BiFunction;
+import java.util.function.Predicate;
+
+import cpw.mods.modlauncher.api.INameMappingService;
+
+import net.fabricmc.mapping.tree.TinyMappingFactory;
+import net.fabricmc.mapping.tree.TinyTree;
+
+public class YarnNamingService implements INameMappingService {
+ private TinyTree mappings = null;
+
+ @Override
+ public String mappingName() {
+ return "srgtoyarn";
+ }
+
+ @Override
+ public String mappingVersion() {
+ return "1";
+ }
+
+ @Override
+ public Map.Entry<String, String> understanding() {
+ return new Pair<>("srg", "mcp");
+ }
+
+ @Override
+ public BiFunction<Domain, String, String> namingFunction() {
+ return this::remap;
+ }
+
+ private TinyTree getMappings() {
+ if (mappings != null) {
+ return mappings;
+ }
+
+ String pathStr = System.getProperty("loom.srgtoyarn.path");
+ if (pathStr == null) throw new RuntimeException("Missing system property 'loom.srgtoyarn.path'!");
+ Path path = Paths.get(pathStr);
+
+ try (BufferedReader reader = Files.newBufferedReader(path)) {
+ mappings = TinyMappingFactory.loadWithDetection(reader);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+
+ return mappings;
+ }
+
+ private String remap(Domain domain, String name) {
+ TinyTree mappings = getMappings();
+
+ switch (domain) {
+ case CLASS:
+ boolean dot = name.contains(".");
+ return find(mappings.getClasses(), def -> maybeReplace(dot, def.getName("srg"), '/', '.').equals(name))
+ .map(def -> maybeReplace(dot, def.getName("named"), '/', '.'))
+ .orElse(name);
+ case METHOD:
+ return mappings.getClasses().stream()
+ .flatMap(def -> def.getMethods().stream())
+ .filter(def -> def.getName("srg").equals(name))
+ .findAny()
+ .map(def -> def.getName("named"))
+ .orElse(name);
+ case FIELD:
+ return mappings.getClasses().stream()
+ .flatMap(def -> def.getFields().stream())
+ .filter(def -> def.getName("srg").equals(name))
+ .findAny()
+ .map(def -> def.getName("named"))
+ .orElse(name);
+ default:
+ return name;
+ }
+ }
+
+ // From CollectionUtil
+ private static <E> Optional<E> find(Iterable<? extends E> collection, Predicate<? super E> filter) {
+ for (E e : collection) {
+ if (filter.test(e)) {
+ return Optional.of(e);
+ }
+ }
+
+ return Optional.empty();
+ }
+
+ private static String maybeReplace(boolean run, String s, char from, char to) {
+ return run ? s.replace(from, to) : s;
+ }
+}
diff --git a/src/forgeInject/resources/META-INF/services/cpw.mods.modlauncher.api.INameMappingService b/src/forgeInject/resources/META-INF/services/cpw.mods.modlauncher.api.INameMappingService
new file mode 100644
index 00000000..45290566
--- /dev/null
+++ b/src/forgeInject/resources/META-INF/services/cpw.mods.modlauncher.api.INameMappingService
@@ -0,0 +1 @@
+net.fabricmc.loom.inject.YarnNamingService
diff --git a/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java b/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java
index 73e763e9..15490f56 100644
--- a/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java
+++ b/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java
@@ -36,6 +36,7 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Collections;
import java.util.Optional;
@@ -275,11 +276,20 @@ public class MinecraftProvider extends DependencyProvider {
private void injectForgeClasses(Logger logger) throws IOException {
logger.lifecycle(":injecting forge classes into minecraft");
- copyAll(getExtension().getForgeUniversalProvider().getForge(), minecraftClientPatchedSrgJar);
- copyAll(getExtension().getForgeUniversalProvider().getForge(), minecraftServerPatchedSrgJar);
+ copyAll(getExtension().getForgeUniversalProvider().getForge().toPath(), minecraftClientPatchedSrgJar.toPath());
+ copyAll(getExtension().getForgeUniversalProvider().getForge().toPath(), minecraftServerPatchedSrgJar.toPath());
- copyUserdevFiles(getExtension().getForgeUserdevProvider().getUserdevJar(), minecraftClientPatchedSrgJar);
- copyUserdevFiles(getExtension().getForgeUserdevProvider().getUserdevJar(), minecraftServerPatchedSrgJar);
+ copyUserdevFiles(getExtension().getForgeUserdevProvider().getUserdevJar().toPath(), minecraftClientPatchedSrgJar.toPath());
+ copyUserdevFiles(getExtension().getForgeUserdevProvider().getUserdevJar().toPath(), minecraftServerPatchedSrgJar.toPath());
+
+ try {
+ logger.lifecycle(":injecting loom classes into minecraft");
+ Path injection = Paths.get(MinecraftProvider.class.getResource("/inject/injection.jar").toURI());
+ copyAll(injection, minecraftClientPatchedSrgJar.toPath());
+ copyAll(injection, minecraftServerPatchedSrgJar.toPath());
+ } catch (URISyntaxException e) {
+ throw new IOException(e);
+ }
}
private void remapPatchedJars(Logger logger) throws IOException {
@@ -317,8 +327,8 @@ public class MinecraftProvider extends DependencyProvider {
patchJars(minecraftServerSrgJar, minecraftServerPatchedSrgJar, patchProvider.serverPatches);
logger.lifecycle(":copying missing classes into patched jars");
- copyMissingClasses(minecraftClientSrgJar, minecraftClientPatchedSrgJar);
- copyMissingClasses(minecraftServerSrgJar, minecraftServerPatchedSrgJar);
+ copyMissingClasses(minecraftClientSrgJar.toPath(), minecraftClientPatchedSrgJar.toPath());
+ copyMissingClasses(minecraftServerSrgJar.toPath(), minecraftServerPatchedSrgJar.toPath());
}
private void patchJars(File clean, File output, Path patches) throws IOException {
@@ -337,8 +347,8 @@ public class MinecraftProvider extends DependencyProvider {
logger.lifecycle(":copying resources");
// Copy resources
- copyNonClassFiles(minecraftClientJar, minecraftMergedJar);
- copyNonClassFiles(minecraftServerJar, minecraftMergedJar);
+ copyNonClassFiles(minecraftClientJar.toPath(), minecraftMergedJar.toPath());
+ copyNonClassFiles(minecraftServerJar.toPath(), minecraftMergedJar.toPath());
} else {
logger.lifecycle(":merging jars");
@@ -349,9 +359,9 @@ public class MinecraftProvider extends DependencyProvider {
}
}
- private void walkFileSystems(File source, File target, Predicate<Path> filter, Function<FileSystem, Iterable<Path>> toWalk, FsPathConsumer action) throws IOException {
- try (FileSystem sourceFs = FileSystems.newFileSystem(new URI("jar:" + source.toURI()), ImmutableMap.of("create", false));
- FileSystem targetFs = FileSystems.newFileSystem(new URI("jar:" + target.toURI()), ImmutableMap.of("create", false))) {
+ private void walkFileSystems(Path source, Path target, Predicate<Path> filter, Function<FileSystem, Iterable<Path>> toWalk, FsPathConsumer action) throws IOException {
+ try (FileSystem sourceFs = FileSystems.newFileSystem(new URI("jar:" + source.toUri()), ImmutableMap.of("create", false));
+ FileSystem targetFs = FileSystems.newFileSystem(new URI("jar:" + target.toUri()), ImmutableMap.of("create", false))) {
for (Path sourceDir : toWalk.apply(sourceFs)) {
Path dir = sourceDir.toAbsolutePath();
java.nio.file.Files.walk(dir)
@@ -374,15 +384,15 @@ public class MinecraftProvider extends DependencyProvider {
}
}
- private void walkFileSystems(File source, File target, Predicate<Path> filter, FsPathConsumer action) throws IOException {
+ private void walkFileSystems(Path source, Path target, Predicate<Path> filter, FsPathConsumer action) throws IOException {
walkFileSystems(source, target, filter, FileSystem::getRootDirectories, action);
}
- private void copyAll(File source, File target) throws IOException {
+ private void copyAll(Path source, Path target) throws IOException {
walkFileSystems(source, target, it -> true, this::copyReplacing);
}
- private void copyMissingClasses(File source, File target) throws IOException {
+ private void copyMissingClasses(Path source, Path target) throws IOException {
walkFileSystems(source, target, it -> it.toString().endsWith(".class"), (sourceFs, targetFs, sourcePath, targetPath) -> {
if (java.nio.file.Files.exists(targetPath)) return;
Path parent = targetPath.getParent();
@@ -395,7 +405,7 @@ public class MinecraftProvider extends DependencyProvider {
});
}
- private void copyNonClassFiles(File source, File target) throws IOException {
+ private void copyNonClassFiles(Path source, Path target) throws IOException {
walkFileSystems(source, target, it -> !it.toString().endsWith(".class"), this::copyReplacing);
}
@@ -409,7 +419,7 @@ public class MinecraftProvider extends DependencyProvider {
java.nio.file.Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
}
- private void copyUserdevFiles(File source, File target) throws IOException {
+ private void copyUserdevFiles(Path source, Path target) throws IOException {
walkFileSystems(source, target, file -> true, fs -> Collections.singleton(fs.getPath("inject")), (sourceFs, targetFs, sourcePath, targetPath) -> {
Path parent = targetPath.getParent();