diff --git a/build.gradle b/build.gradle index 87f7696b..7f3e2490 100644 --- a/build.gradle +++ b/build.gradle @@ -28,6 +28,10 @@ repositories { name = 'Mojang' url = 'https://libraries.minecraft.net/' } + maven { + name = 'SpongePowered' + url = 'http://repo.spongepowered.org/maven' + } } configurations { @@ -53,6 +57,10 @@ dependencies { //Always fun when your dep needs the tool to build, but the tool needs the dep. //compile 'net.fabricmc:fabric-base:16w38a-0.0.4-SNAPSHOT' + shade('org.spongepowered:mixin:0.6.8-SNAPSHOT') { + exclude module: 'launchwrapper' + exclude module: 'guava' + } shade 'org.apache.commons:commons-lang3:3.5' } diff --git a/src/main/java/net/fabricmc/loom/AbstractPlugin.java b/src/main/java/net/fabricmc/loom/AbstractPlugin.java index c792af01..b4c99b29 100644 --- a/src/main/java/net/fabricmc/loom/AbstractPlugin.java +++ b/src/main/java/net/fabricmc/loom/AbstractPlugin.java @@ -82,6 +82,37 @@ public class AbstractPlugin implements Plugin { configureIDEs(); configureCompile(); + + Map> taskMap = project.getAllTasks(true); + for (Map.Entry> entry : taskMap.entrySet()) { + Project project = entry.getKey(); + Set taskSet = entry.getValue(); + for (Task task : taskSet) { + if (task instanceof JavaCompile + && !(task.getName().contains("Test")) && !(task.getName().contains("test"))) { + JavaCompile javaCompileTask = (JavaCompile) task; + javaCompileTask.doFirst(task1 -> { + project.getLogger().lifecycle(":setting java compiler args"); + try { + 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()); + if(extension.refmapName == null || extension.refmapName.isEmpty()){ + project.getLogger().error("Could not find refmap definition, will be using default name: " + project.getName() + "-refmap.json"); + extension.refmapName = project.getName() + "-refmap.json"; + } + javaCompileTask.getOptions().getCompilerArgs().add("-AoutRefMapFile=" + new File(javaCompileTask.getDestinationDir(), extension.refmapName).getCanonicalPath()); + javaCompileTask.getOptions().getCompilerArgs().add("-AdefaultObfuscationEnv=pomf:mojang"); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + } + + } + } /** diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java index 3b025088..2ffb1962 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java +++ b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java @@ -33,6 +33,7 @@ public class LoomGradleExtension { public String runDir = "run"; public String fabricVersion; public String pomfVersion; + public String refmapName; public boolean localMappings = false; //Not to be set in the build.gradle 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 00000000..e63db8e9 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/mixin/MixinMappingProviderTiny.java @@ -0,0 +1,144 @@ +/* + * 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 net.fabricmc.tinyremapper.TinyUtils; +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.nio.file.Files; + +public class MixinMappingProviderTiny extends MappingProvider { + private final String from, to; + + 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()); + + TinyUtils.read(reader, from, to, (classFrom, classTo) -> { + classMap.put(classFrom, classTo); + }, (fieldFrom, fieldTo) -> { + fieldMap.put( + new MappingField(fieldFrom.owner, fieldFrom.name, fieldFrom.desc), + new MappingField(fieldTo.owner, fieldTo.name, fieldTo.desc) + ); + }, (methodFrom, methodTo) -> { + methodMap.put( + new MappingMethod(methodFrom.owner, methodFrom.name, methodFrom.desc), + new MappingMethod(methodTo.owner, methodTo.name, methodTo.desc) + ); + }); + } +} 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 00000000..0ea4a47a --- /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 00000000..70318e44 --- /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 00000000..b95f7195 --- /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/Constants.java b/src/main/java/net/fabricmc/loom/util/Constants.java index 8f9634f3..40a792be 100644 --- a/src/main/java/net/fabricmc/loom/util/Constants.java +++ b/src/main/java/net/fabricmc/loom/util/Constants.java @@ -48,14 +48,16 @@ public class Constants { public static final IDelayed MAPPINGS_DIR = new DelayedFile(extension -> new File(POMF_DIR.get(extension), "pomf-enigma-" + extension.version + "." + extension.pomfVersion + "")); public static IDelayed MAPPINGS_TINY_GZ = new DelayedFile(extension -> new File(POMF_DIR.get(extension), "pomf-tiny-" + extension.version + "." + extension.pomfVersion + ".gz")); public static final IDelayed MAPPINGS_TINY = new DelayedFile(extension -> new File(POMF_DIR.get(extension), "pomf-tiny-" + extension.version + "." + extension.pomfVersion)); + public static final IDelayed MAPPINGS_MIXIN_EXPORT = new DelayedFile(extension -> new File(CACHE_FILES, "mixin-map-" + extension.version + "." + extension.pomfVersion + ".mappings")); public static final IDelayed MAPPINGS_DIR_LOCAL = new DelayedFile(extension -> new File(WORKING_DIRECTORY, "mappings")); public static final IDelayed MAPPINGS_ZIP_LOCAL = new DelayedFile(extension -> new File(MAPPINGS_DIR_LOCAL.get(extension), "pomf-enigma-" + extension.version + ".zip")); public static final IDelayed MAPPINGS_TINY_GZ_LOCAL = new DelayedFile(extension -> new File(MAPPINGS_DIR_LOCAL.get(extension), "pomf-tiny-" + extension.version + ".gz")); - + public static final IDelayed MINECRAFT_LIBS = new DelayedFile(extension -> new File(extension.getUserCache(), extension.version + "-libs")); public static final IDelayed MINECRAFT_NATIVES = new DelayedFile(extension -> new File(extension.getUserCache(), extension.version + "-natives")); public static final IDelayed MINECRAFT_JSON = new DelayedFile(extension -> new File(extension.getUserCache(), extension.version + "-info.json")); + public static final IDelayed REF_MAP = new DelayedFile(extension -> new File(CACHE_FILES, "mixin-refmap.json")); public static final IDelayed VERSION_MANIFEST = new DelayedFile(extension -> new File(extension.getUserCache(), "version_manifest.json")); diff --git a/src/main/java/net/fabricmc/loom/util/ModRemapper.java b/src/main/java/net/fabricmc/loom/util/ModRemapper.java index aa0d71f4..20d0ddd7 100644 --- a/src/main/java/net/fabricmc/loom/util/ModRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/ModRemapper.java @@ -74,6 +74,7 @@ public class ModRemapper { TinyRemapper remapper = TinyRemapper.newRemapper() .withMappings(TinyUtils.createTinyMappingProvider(mappings, fromM, toM)) + .withMappings(TinyUtils.createTinyMappingProvider(Constants.MAPPINGS_MIXIN_EXPORT.get(extension).toPath(), toM, fromM)) .build(); OutputConsumerPath outputConsumer = new OutputConsumerPath(modJar.toPath());