diff --git a/src/main/java/net/fabricmc/loom/AbstractPlugin.java b/src/main/java/net/fabricmc/loom/AbstractPlugin.java index 4d2c1a8..4e98604 100644 --- a/src/main/java/net/fabricmc/loom/AbstractPlugin.java +++ b/src/main/java/net/fabricmc/loom/AbstractPlugin.java @@ -37,6 +37,7 @@ import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.artifacts.repositories.MavenArtifactRepository; +import org.gradle.api.internal.file.collections.FileCollectionAdapter; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.tasks.SourceSet; @@ -100,10 +101,10 @@ public class AbstractPlugin implements Plugin { javaCompileTask.doFirst(task1 -> { project.getLogger().lifecycle(":setting java compiler args"); try { - javaCompileTask.getOptions().getCompilerArgs().add("-AinMapFile=" + Constants.MAPPINGS_TINY.get(extension).getCanonicalPath()); - javaCompileTask.getOptions().getCompilerArgs().add("-AoutMapFile=" + Constants.MAPPINGS_TINY.get(extension).getCanonicalPath()); + javaCompileTask.getClasspath().add(target.files(this.getClass().getProtectionDomain().getCodeSource().getLocation())); + javaCompileTask.getOptions().getCompilerArgs().add("-AinMapFilePomfMojang=" + Constants.MAPPINGS_TINY.get(extension).getCanonicalPath()); + javaCompileTask.getOptions().getCompilerArgs().add("-AoutMapFilePomfMojang=" + Constants.MAPPINGS_MIXIN_EXPORT.get(extension).getCanonicalPath()); javaCompileTask.getOptions().getCompilerArgs().add("-AoutRefMapFile=" + Constants.REF_MAP.get(extension).getCanonicalPath()); - javaCompileTask.getOptions().getCompilerArgs().add("-AdefaultObfuscationEnv=mojang"); //TODO check if this should be pomf? } catch (IOException e) { e.printStackTrace(); } diff --git a/src/main/java/net/fabricmc/loom/mixin/MixinMappingProviderTiny.java b/src/main/java/net/fabricmc/loom/mixin/MixinMappingProviderTiny.java new file mode 100644 index 0000000..8701171 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/mixin/MixinMappingProviderTiny.java @@ -0,0 +1,196 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016 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.mixin; + +import cuchaz.enigma.analysis.Access; +import org.objectweb.asm.commons.Remapper; +import org.spongepowered.asm.obfuscation.mapping.common.MappingField; +import org.spongepowered.asm.obfuscation.mapping.common.MappingMethod; +import org.spongepowered.tools.obfuscation.mapping.common.MappingProvider; + +import javax.annotation.processing.Filer; +import javax.annotation.processing.Messager; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.nio.file.Files; +import java.util.*; + +public class MixinMappingProviderTiny extends MappingProvider { + private final String from, to; + + private static class SimpleClassMapper extends Remapper { + final Map classMap; + + public SimpleClassMapper(Map map) { + this.classMap = map; + } + + @Override + public String map(String typeName) { + return classMap.get(typeName); + } + } + + public MixinMappingProviderTiny(Messager messager, Filer filer, String from, String to) { + super(messager, filer); + this.from = from; + this.to = to; + } + + private static final String[] removeFirst(String[] src, int count) { + if (count >= src.length) { + return new String[0]; + } else { + String[] out = new String[src.length - count]; + System.arraycopy(src, count, out, 0, out.length); + return out; + } + } + + + @Override + public MappingMethod getMethodMapping(MappingMethod method) { + System.out.println("processing " + method.getName() + method.getDesc()); + + MappingMethod mapped = this.methodMap.get(method); + if (mapped != null) return mapped; + + try { + Class c = this.getClass().getClassLoader().loadClass(method.getOwner().replace('/', '.')); + if (c == null || c == Object.class) { + return null; + } + + for (Class cc : c.getInterfaces()) { + mapped = getMethodMapping(method.move(cc.getName().replace('.', '/'))); + if (mapped != null) return mapped; + } + + if (c.getSuperclass() != null) { + mapped = getMethodMapping(method.move(c.getSuperclass().getName().replace('.', '/'))); + if (mapped != null) return mapped; + } + + return null; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + @Override + public MappingField getFieldMapping(MappingField field) { + System.out.println("processing " + field.getOwner() + "/" + field.getName() + field.getDesc()); + + MappingField mapped = this.fieldMap.get(field); + if (mapped != null) return mapped; + + try { + Class c = this.getClass().getClassLoader().loadClass(field.getOwner().replace('/', '.')); + if (c == null || c == Object.class) { + return null; + } + + for (Class cc : c.getInterfaces()) { + mapped = getFieldMapping(field.move(cc.getName().replace('.', '/'))); + if (mapped != null) return mapped; + } + + if (c.getSuperclass() != null) { + mapped = getFieldMapping(field.move(c.getSuperclass().getName().replace('.', '/'))); + if (mapped != null) return mapped; + } + + return null; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + // TODO: Unify with tiny-remapper + + @Override + public void read(File input) throws IOException { + BufferedReader reader = Files.newBufferedReader(input.toPath()); + String[] header = reader.readLine().split("\t"); + if (header.length <= 1 + || !header[0].equals("v1")) { + throw new IOException("Invalid mapping version!"); + } + + List headerList = Arrays.asList(removeFirst(header, 1)); + int fromIndex = headerList.indexOf(from); + int toIndex = headerList.indexOf(to); + + if (fromIndex < 0) throw new IOException("Could not find mapping '" + from + "'!"); + if (toIndex < 0) throw new IOException("Could not find mapping '" + to + "'!"); + + Map obfFrom = new HashMap<>(); + Map obfTo = new HashMap<>(); + List linesStageTwo = new ArrayList<>(); + + String line; + while ((line = reader.readLine()) != null) { + String[] splitLine = line.split("\t"); + if (splitLine.length >= 2) { + if ("CLASS".equals(splitLine[0])) { + classMap.put(splitLine[1 + fromIndex], splitLine[1 + toIndex]); + obfFrom.put(splitLine[1], splitLine[1 + fromIndex]); + obfTo.put(splitLine[1], splitLine[1 + toIndex]); + } else { + linesStageTwo.add(splitLine); + } + } + } + + SimpleClassMapper descObfFrom = new SimpleClassMapper(obfFrom); + SimpleClassMapper descObfTo = new SimpleClassMapper(obfTo); + + for (String[] splitLine : linesStageTwo) { + if ("FIELD".equals(splitLine[0])) { + String ownerFrom = obfFrom.getOrDefault(splitLine[1], splitLine[1]); + String ownerTo = obfTo.getOrDefault(splitLine[1], splitLine[1]); + String descFrom = descObfFrom.mapDesc(splitLine[2]); + String descTo = descObfTo.mapDesc(splitLine[2]); + fieldMap.put( + new MappingField(ownerFrom, splitLine[3 + fromIndex], descFrom), + new MappingField(ownerTo, splitLine[3 + toIndex], descTo) + ); + } else if ("METHOD".equals(splitLine[0])) { + String ownerFrom = obfFrom.getOrDefault(splitLine[1], splitLine[1]); + String ownerTo = obfTo.getOrDefault(splitLine[1], splitLine[1]); + String descFrom = descObfFrom.mapMethodDesc(splitLine[2]); + String descTo = descObfTo.mapMethodDesc(splitLine[2]); + methodMap.put( + new MappingMethod(ownerFrom, splitLine[3 + fromIndex], descFrom), + new MappingMethod(ownerTo, splitLine[3 + toIndex], descTo) + ); + } + } + } +} diff --git a/src/main/java/net/fabricmc/loom/mixin/MixinMappingWriterTiny.java b/src/main/java/net/fabricmc/loom/mixin/MixinMappingWriterTiny.java new file mode 100644 index 0000000..1631f45 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/mixin/MixinMappingWriterTiny.java @@ -0,0 +1,75 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016 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.mixin; + +import org.spongepowered.asm.obfuscation.mapping.common.MappingField; +import org.spongepowered.asm.obfuscation.mapping.common.MappingMethod; +import org.spongepowered.tools.obfuscation.ObfuscationType; +import org.spongepowered.tools.obfuscation.mapping.IMappingConsumer; +import org.spongepowered.tools.obfuscation.mapping.common.MappingWriter; + +import javax.annotation.processing.Filer; +import javax.annotation.processing.Messager; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * Created by asie on 10/9/16. + */ +public class MixinMappingWriterTiny extends MappingWriter { + public MixinMappingWriterTiny(Messager messager, Filer filer) { + super(messager, filer); + } + + @Override + public void write(String output, ObfuscationType type, IMappingConsumer.MappingSet fields, IMappingConsumer.MappingSet methods) { + if (output != null) { + PrintWriter writer = null; + + try { + String from = type.getKey().split(":")[0]; + String to = type.getKey().split(":")[1]; + + writer = this.openFileWriter(output, type + " output TinyMappings"); + writer.println(String.format("v1\t%s\t%s", from, to)); + for (IMappingConsumer.MappingSet.Pair pair : fields) { + writer.println(String.format("FIELD\t%s\t%s\t%s\t%s", pair.from.getOwner(), pair.from.getDesc(), pair.from.getSimpleName(), pair.to.getSimpleName())); + } + for (IMappingConsumer.MappingSet.Pair pair : methods) { + writer.println(String.format("METHOD\t%s\t%s\t%s\t%s", pair.from.getOwner(), pair.from.getDesc(), pair.from.getSimpleName(), pair.to.getSimpleName())); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (Exception e) { + } + } + } + } + } +} diff --git a/src/main/java/net/fabricmc/loom/mixin/ObfuscationEnvironmentFabric.java b/src/main/java/net/fabricmc/loom/mixin/ObfuscationEnvironmentFabric.java new file mode 100644 index 0000000..3b2166b --- /dev/null +++ b/src/main/java/net/fabricmc/loom/mixin/ObfuscationEnvironmentFabric.java @@ -0,0 +1,51 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016 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.mixin; + +import org.spongepowered.tools.obfuscation.ObfuscationEnvironment; +import org.spongepowered.tools.obfuscation.ObfuscationType; +import org.spongepowered.tools.obfuscation.mapping.IMappingProvider; +import org.spongepowered.tools.obfuscation.mapping.IMappingWriter; + +import javax.annotation.processing.Filer; +import javax.annotation.processing.Messager; + +public class ObfuscationEnvironmentFabric extends ObfuscationEnvironment { + protected ObfuscationEnvironmentFabric(ObfuscationType type) { + super(type); + } + + @Override + protected IMappingProvider getMappingProvider(Messager messager, Filer filer) { + String from = type.getKey().split(":")[0]; + String to = type.getKey().split(":")[1]; + return new MixinMappingProviderTiny(messager, filer, from, to); + } + + @Override + protected IMappingWriter getMappingWriter(Messager messager, Filer filer) { + return new MixinMappingWriterTiny(messager, filer); + } +} diff --git a/src/main/java/net/fabricmc/loom/mixin/ObfuscationServiceFabric.java b/src/main/java/net/fabricmc/loom/mixin/ObfuscationServiceFabric.java new file mode 100644 index 0000000..3430a1a --- /dev/null +++ b/src/main/java/net/fabricmc/loom/mixin/ObfuscationServiceFabric.java @@ -0,0 +1,75 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016 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.mixin; + +import com.google.common.collect.ImmutableSet; +import org.apache.commons.lang3.StringUtils; +import org.spongepowered.tools.obfuscation.service.IObfuscationService; +import org.spongepowered.tools.obfuscation.service.ObfuscationTypeDescriptor; + +import java.util.Collection; +import java.util.Set; + +public class ObfuscationServiceFabric implements IObfuscationService { + public static final String IN_MAP_FILE = "inMapFile"; + public static final String IN_MAP_EXTRA_FILES = "inMapExtraFiles"; + public static final String OUT_MAP_FILE = "outMapFile"; + + private String asSuffixed(String arg, String from, String to) { + return arg + StringUtils.capitalize(from) + StringUtils.capitalize(to); + } + + private ObfuscationTypeDescriptor createObfuscationType(String from, String to) { + return new ObfuscationTypeDescriptor( + from + ":" + to, + asSuffixed(ObfuscationServiceFabric.IN_MAP_FILE, from, to), + asSuffixed(ObfuscationServiceFabric.IN_MAP_EXTRA_FILES, from, to), + asSuffixed(ObfuscationServiceFabric.OUT_MAP_FILE, from, to), + ObfuscationEnvironmentFabric.class + ); + } + + private void addSupportedOptions(ImmutableSet.Builder builder, String from, String to) { + builder.add(asSuffixed(ObfuscationServiceFabric.IN_MAP_FILE, from, to)); + builder.add(asSuffixed(ObfuscationServiceFabric.IN_MAP_EXTRA_FILES, from, to)); + builder.add(asSuffixed(ObfuscationServiceFabric.OUT_MAP_FILE, from, to)); + } + + @Override + public Set getSupportedOptions() { + ImmutableSet.Builder builder = new ImmutableSet.Builder(); + addSupportedOptions(builder, "mojang", "pomf"); + addSupportedOptions(builder, "pomf", "mojang"); + return builder.build(); + } + + @Override + public Collection getObfuscationTypes() { + return ImmutableSet.of( + createObfuscationType("mojang", "pomf"), + createObfuscationType("pomf", "mojang") + ); + } +} diff --git a/src/main/java/net/fabricmc/loom/util/ModRemapper.java b/src/main/java/net/fabricmc/loom/util/ModRemapper.java index a49c99a..d81a290 100644 --- a/src/main/java/net/fabricmc/loom/util/ModRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/ModRemapper.java @@ -25,7 +25,7 @@ package net.fabricmc.loom.util; import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.tinyremapper.OutputConsumerJar; +import net.fabricmc.tinyremapper.OutputConsumerPath; import net.fabricmc.tinyremapper.TinyRemapper; import net.fabricmc.tinyremapper.TinyUtils; import org.gradle.api.Project; @@ -69,8 +69,8 @@ public class ModRemapper { .withMappings(TinyUtils.createTinyMappingProvider(mappings, fromM, toM)) .build(); - OutputConsumerJar outputConsumer = new OutputConsumerJar(modOutputJar); - outputConsumer.addNonClassFiles(modJar); + OutputConsumerPath outputConsumer = new OutputConsumerPath(modOutputJar.toPath()); + outputConsumer.addNonClassFiles(modJar.toPath()); remapper.read(modJar.toPath()); remapper.read(classpath); remapper.apply(modJar.toPath(), outputConsumer); diff --git a/src/main/resources/META-INF/services/org.spongepowered.tools.obfuscation.service.IObfuscationService b/src/main/resources/META-INF/services/org.spongepowered.tools.obfuscation.service.IObfuscationService new file mode 100644 index 0000000..b3949cc --- /dev/null +++ b/src/main/resources/META-INF/services/org.spongepowered.tools.obfuscation.service.IObfuscationService @@ -0,0 +1 @@ +net.fabricmc.loom.mixin.ObfuscationServiceFabric \ No newline at end of file