Remove a bunch of stuff + update to support modlauncher
This commit is contained in:
		
							parent
							
								
									8bf709adf9
								
							
						
					
					
						commit
						6b59f9cc59
					
				
					 21 changed files with 16 additions and 936 deletions
				
			
		
							
								
								
									
										19
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								build.gradle
									
									
									
									
									
								
							|  | @ -13,7 +13,7 @@ targetCompatibility = 1.8 | ||||||
| 
 | 
 | ||||||
| group = 'com.openmodloader' | group = 'com.openmodloader' | ||||||
| archivesBaseName = project.name | archivesBaseName = project.name | ||||||
| version = '0.0.9-SNAPSHOT' | version = '0.0.10-SNAPSHOT' | ||||||
| 
 | 
 | ||||||
| repositories { | repositories { | ||||||
|     mavenCentral() |     mavenCentral() | ||||||
|  | @ -30,8 +30,8 @@ repositories { | ||||||
| 		url = 'https://libraries.minecraft.net/' | 		url = 'https://libraries.minecraft.net/' | ||||||
| 	} | 	} | ||||||
| 	maven { | 	maven { | ||||||
| 		name = 'SpongePowered' | 		name = 'Forge' //For ModLauncher | ||||||
| 		url = 'http://repo.spongepowered.org/maven' | 		url = 'http://files.minecraftforge.net/maven/' | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -61,17 +61,8 @@ dependencies { | ||||||
| 	shade 'org.apache.logging.log4j:log4j-core:2.11.0' | 	shade 'org.apache.logging.log4j:log4j-core:2.11.0' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	shade ('net.minecraft:launchwrapper:1.12') { | 	shade 'cpw.mods:modlauncher:0.1.0-rc.3' | ||||||
| 		transitive = false |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	//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.7.8-SNAPSHOT') { |  | ||||||
| 		exclude module: 'launchwrapper' |  | ||||||
| 		exclude module: 'guava' |  | ||||||
| 	} |  | ||||||
| 	shade 'org.apache.commons:commons-lang3:3.5' | 	shade 'org.apache.commons:commons-lang3:3.5' | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | @ -93,7 +84,7 @@ jar { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| task wrapper(type: Wrapper) { | task wrapper(type: Wrapper) { | ||||||
|     gradleVersion = '4.7' |     gradleVersion = '4.9' | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| publishing { | publishing { | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										3
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							|  | @ -1,6 +1,5 @@ | ||||||
| #Mon May 14 11:21:37 BST 2018 |  | ||||||
| distributionBase=GRADLE_USER_HOME | distributionBase=GRADLE_USER_HOME | ||||||
| distributionPath=wrapper/dists | distributionPath=wrapper/dists | ||||||
|  | distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip | ||||||
| zipStoreBase=GRADLE_USER_HOME | zipStoreBase=GRADLE_USER_HOME | ||||||
| zipStorePath=wrapper/dists | zipStorePath=wrapper/dists | ||||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-all.zip |  | ||||||
|  |  | ||||||
|  | @ -87,36 +87,6 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 		configureIDEs(); | 		configureIDEs(); | ||||||
| 		configureCompile(); | 		configureCompile(); | ||||||
| 
 | 
 | ||||||
| 		Map<Project, Set<Task>> taskMap = project.getAllTasks(true); |  | ||||||
| 		for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) { |  | ||||||
| 			Project project = entry.getKey(); |  | ||||||
| 			Set<Task> 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(); |  | ||||||
| 						} |  | ||||||
| 					}); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  | @ -217,11 +187,6 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 				mavenArtifactRepository.setUrl("https://maven.modmuss50.me"); | 				mavenArtifactRepository.setUrl("https://maven.modmuss50.me"); | ||||||
| 			}); | 			}); | ||||||
| 
 | 
 | ||||||
| 			project1.getRepositories().maven(mavenArtifactRepository -> { |  | ||||||
| 				mavenArtifactRepository.setName("SpongePowered"); |  | ||||||
| 				mavenArtifactRepository.setUrl("http://repo.spongepowered.org/maven"); |  | ||||||
| 			}); |  | ||||||
| 
 |  | ||||||
| 			project1.getRepositories().maven(mavenArtifactRepository -> { | 			project1.getRepositories().maven(mavenArtifactRepository -> { | ||||||
| 				mavenArtifactRepository.setName("Mojang"); | 				mavenArtifactRepository.setName("Mojang"); | ||||||
| 				mavenArtifactRepository.setUrl("https://libraries.minecraft.net/"); | 				mavenArtifactRepository.setUrl("https://libraries.minecraft.net/"); | ||||||
|  | @ -250,7 +215,7 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 
 | 
 | ||||||
| 			if (extension.omlVersion != null && !extension.omlVersion.isEmpty()) { | 			if (extension.omlVersion != null && !extension.omlVersion.isEmpty()) { | ||||||
| 				//only add this when not in a fabric dev env | 				//only add this when not in a fabric dev env | ||||||
| 				project1.getDependencies().add(Constants.COMPILE_MODS, "OpenModLoader:OpenModLoader:" + extension.version + "-" + extension.omlVersion); | 				project1.getDependencies().add(Constants.CONFIG_MC_DEPENDENCIES, "OpenModLoader:OpenModLoader:" + extension.version + "-" + extension.omlVersion); | ||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -33,7 +33,6 @@ public class LoomGradleExtension { | ||||||
| 	public String runDir = "run"; | 	public String runDir = "run"; | ||||||
| 	public String omlVersion; | 	public String omlVersion; | ||||||
| 	public String pomfVersion; | 	public String pomfVersion; | ||||||
| 	public String refmapName; |  | ||||||
| 	public boolean skipPrebake = false; | 	public boolean skipPrebake = false; | ||||||
| 	public boolean localMappings = false; | 	public boolean localMappings = false; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,144 +0,0 @@ | ||||||
| /* |  | ||||||
|  * 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) |  | ||||||
| 			); |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -1,75 +0,0 @@ | ||||||
| /* |  | ||||||
|  * 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<MappingField> fields, IMappingConsumer.MappingSet<MappingMethod> 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<MappingField> 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<MappingMethod> 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) { |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -1,77 +0,0 @@ | ||||||
| package net.fabricmc.loom.mixin; |  | ||||||
| 
 |  | ||||||
| import com.google.common.io.ByteStreams; |  | ||||||
| import net.fabricmc.loom.task.ProcessModsTask; |  | ||||||
| import net.fabricmc.loom.util.proccessing.MixinPrebaker; |  | ||||||
| import org.spongepowered.asm.service.IClassBytecodeProvider; |  | ||||||
| import org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper; |  | ||||||
| 
 |  | ||||||
| import java.io.File; |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.io.InputStream; |  | ||||||
| import java.util.ArrayList; |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.Set; |  | ||||||
| import java.util.jar.JarFile; |  | ||||||
| import java.util.zip.ZipEntry; |  | ||||||
| 
 |  | ||||||
| public class MixinServiceGradle extends MixinServiceLaunchWrapper implements IClassBytecodeProvider { |  | ||||||
| 
 |  | ||||||
| 	private static List<JarFile> jars = new ArrayList<>(); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	@Override |  | ||||||
| 	public String getName() { |  | ||||||
| 		return "OpenModLoaderGradle"; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	@Override |  | ||||||
| 	public InputStream getResourceAsStream(String name) { |  | ||||||
| 		if(MixinPrebaker.jarFileCache.containsKey(name)){ |  | ||||||
| 			return MixinPrebaker.jarFileCache.get(name); |  | ||||||
| 		} |  | ||||||
| 		for(JarFile file : jars){ |  | ||||||
| 			ZipEntry entry = file.getEntry(name); |  | ||||||
| 			if(entry != null){ |  | ||||||
| 				try { |  | ||||||
| 					InputStream stream = file.getInputStream(entry); |  | ||||||
| 					return stream; |  | ||||||
| 				} catch (IOException e) { |  | ||||||
| 					throw new RuntimeException("Failed to read mod file", e); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		return super.getResourceAsStream(name); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	public static void setupModFiles(Set<File> mods, File minecraft) throws IOException { |  | ||||||
| 		jars.clear(); |  | ||||||
| 		for(File mod : mods){ |  | ||||||
| 			JarFile jarFile = new JarFile(mod); |  | ||||||
| 			jars.add(jarFile); |  | ||||||
| 		} |  | ||||||
| 		jars.add(new JarFile(minecraft)); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	public static void addMCDeps(Set<File> deps, Object object) throws IOException { |  | ||||||
| 		for(File mod : deps){ |  | ||||||
| 			JarFile jarFile = new JarFile(mod); |  | ||||||
| 			jars.add(jarFile); |  | ||||||
| 			ProcessModsTask.addFile(mod, object); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	@Override |  | ||||||
| 	public IClassBytecodeProvider getBytecodeProvider() { |  | ||||||
| 		return this; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	public byte[] getClassBytes(String name, String transformedName) throws IOException { |  | ||||||
| 		InputStream inputStream = getResourceAsStream(name.replace(".", "/") + ".class"); |  | ||||||
| 		byte[] classBytes = ByteStreams.toByteArray(inputStream); |  | ||||||
| 		if(classBytes == null){ |  | ||||||
| 			return super.getClassBytes(name, transformedName); |  | ||||||
| 		} |  | ||||||
| 		return classBytes; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -1,51 +0,0 @@ | ||||||
| /* |  | ||||||
|  * 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); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -1,75 +0,0 @@ | ||||||
| /* |  | ||||||
|  * 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<String> getSupportedOptions() { |  | ||||||
| 		ImmutableSet.Builder builder = new ImmutableSet.Builder(); |  | ||||||
| 		addSupportedOptions(builder, "mojang", "pomf"); |  | ||||||
| 		addSupportedOptions(builder, "pomf", "mojang"); |  | ||||||
| 		return builder.build(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	@Override |  | ||||||
| 	public Collection<ObfuscationTypeDescriptor> getObfuscationTypes() { |  | ||||||
| 		return ImmutableSet.of( |  | ||||||
| 			createObfuscationType("mojang", "pomf"), |  | ||||||
| 			createObfuscationType("pomf", "mojang") |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -135,22 +135,22 @@ public class GenIdeaProjectTask extends DefaultTask { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		IdeaRunConfig ideaClient = new IdeaRunConfig(); | 		IdeaRunConfig ideaClient = new IdeaRunConfig(); | ||||||
| 		ideaClient.mainClass = "net.minecraft.launchwrapper.Launch"; | 		ideaClient.mainClass = "cpw.mods.modlauncher.Launcher"; | ||||||
| 		ideaClient.projectName = project.getName(); | 		ideaClient.projectName = project.getName(); | ||||||
| 		ideaClient.configName = "Minecraft Client"; | 		ideaClient.configName = "Minecraft Client"; | ||||||
| 		ideaClient.runDir = "file://$PROJECT_DIR$/" + extension.runDir; | 		ideaClient.runDir = "file://$PROJECT_DIR$/" + extension.runDir; | ||||||
| 		ideaClient.vmArgs = "-Djava.library.path=" + Constants.MINECRAFT_NATIVES.get(extension).getAbsolutePath() + " -Doml.development=true"; | 		ideaClient.vmArgs = "-Djava.library.path=" + Constants.MINECRAFT_NATIVES.get(extension).getAbsolutePath() + " -Doml.development=true"; | ||||||
| 		ideaClient.programArgs = "--tweakClass com.openmodloader.loader.launch.OpenClientTweaker --assetIndex " + version.assetIndex.id + " --assetsDir " + new File(extension.getUserCache(), "assets-" + extension.version).getAbsolutePath(); | 		ideaClient.programArgs = "--launchTarget oml --accessToken not_a_real_token --version " + extension.version + " --assetIndex " + version.assetIndex.id + " --assetsDir " + new File(extension.getUserCache(), "assets-" + extension.version).getAbsolutePath(); | ||||||
| 
 | 
 | ||||||
| 		runManager.appendChild(ideaClient.genRuns(runManager)); | 		runManager.appendChild(ideaClient.genRuns(runManager)); | ||||||
| 
 | 
 | ||||||
| 		IdeaRunConfig ideaServer = new IdeaRunConfig(); | 		IdeaRunConfig ideaServer = new IdeaRunConfig(); | ||||||
| 		ideaServer.mainClass = "net.minecraft.launchwrapper.Launch"; | 		ideaServer.mainClass = "com.openmodloader.loader.launch.ServerLauncher"; | ||||||
| 		ideaServer.projectName = project.getName(); | 		ideaServer.projectName = project.getName(); | ||||||
| 		ideaServer.configName = "Minecraft Server"; | 		ideaServer.configName = "Minecraft Server"; | ||||||
| 		ideaServer.runDir = "file://$PROJECT_DIR$/" + extension.runDir; | 		ideaServer.runDir = "file://$PROJECT_DIR$/" + extension.runDir; | ||||||
| 		ideaServer.vmArgs = "-Doml.development=true"; | 		ideaServer.vmArgs = "-Doml.development=true"; | ||||||
| 		ideaServer.programArgs = "--tweakClass com.openmodloader.loader.launch.OpenServerTweaker"; | 		ideaServer.programArgs = ""; | ||||||
| 
 | 
 | ||||||
| 		runManager.appendChild(ideaServer.genRuns(runManager)); | 		runManager.appendChild(ideaServer.genRuns(runManager)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -49,7 +49,7 @@ public class MapJarsTask extends DefaultTask { | ||||||
| 	@TaskAction | 	@TaskAction | ||||||
| 	public void mapJars() throws IOException, MappingParseException { | 	public void mapJars() throws IOException, MappingParseException { | ||||||
| 		LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 		if (!Constants.MINECRAFT_MAPPED_JAR.get(extension).exists() || extension.localMappings || true) { | 		if (!Constants.MINECRAFT_MAPPED_JAR.get(extension).exists() || extension.localMappings) { | ||||||
| 			if(extension.localMappings && Constants.MINECRAFT_MAPPED_JAR.get(extension).exists()){ | 			if(extension.localMappings && Constants.MINECRAFT_MAPPED_JAR.get(extension).exists()){ | ||||||
| 				//Always remap the jar when using local mappings. | 				//Always remap the jar when using local mappings. | ||||||
| 				Constants.MINECRAFT_MAPPED_JAR.get(extension).delete(); | 				Constants.MINECRAFT_MAPPED_JAR.get(extension).delete(); | ||||||
|  |  | ||||||
|  | @ -26,7 +26,6 @@ package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.util.Constants; | import net.fabricmc.loom.util.Constants; | ||||||
| import net.fabricmc.loom.util.proccessing.PreBakeMixins; |  | ||||||
| import org.apache.commons.io.FileUtils; | import org.apache.commons.io.FileUtils; | ||||||
| import org.gradle.api.DefaultTask; | import org.gradle.api.DefaultTask; | ||||||
| import org.gradle.api.artifacts.Configuration; | import org.gradle.api.artifacts.Configuration; | ||||||
|  | @ -57,11 +56,10 @@ public class ProcessModsTask extends DefaultTask { | ||||||
| 			Constants.MINECRAFT_FINAL_JAR.get(extension).delete(); | 			Constants.MINECRAFT_FINAL_JAR.get(extension).delete(); | ||||||
| 		} | 		} | ||||||
| 		if (mods.size() == 0 || extension.skipPrebake) { | 		if (mods.size() == 0 || extension.skipPrebake) { | ||||||
| 			getProject().getLogger().lifecycle(":skipping mixin prebake"); |  | ||||||
| 			FileUtils.copyFile(Constants.MINECRAFT_MERGED_JAR.get(extension), Constants.MINECRAFT_MIXED_JAR.get(extension)); | 			FileUtils.copyFile(Constants.MINECRAFT_MERGED_JAR.get(extension), Constants.MINECRAFT_MIXED_JAR.get(extension)); | ||||||
| 		} else { | 		} else { | ||||||
| 			downloadRequiredDeps(extension); | //			downloadRequiredDeps(extension); | ||||||
| 			new PreBakeMixins().proccess(getProject(), extension, mods); | 			throw new UnsupportedOperationException("Mixin prebake isnt done yet"); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -68,7 +68,7 @@ public class RunClientTask extends JavaExec { | ||||||
| 		libs.add(Constants.MINECRAFT_CLIENT_JAR.get(extension).getAbsolutePath()); | 		libs.add(Constants.MINECRAFT_CLIENT_JAR.get(extension).getAbsolutePath()); | ||||||
| 		classpath(libs); | 		classpath(libs); | ||||||
| 
 | 
 | ||||||
| 		args("--tweakClass", "com.openmodloader.loader.launch.OpenClientTweaker", "--assetIndex", version.assetIndex.id, "--assetsDir", new File(extension.getUserCache(), "assets-" + extension.version).getAbsolutePath()); | 		args("--launchTarget", "oml", "--accessToken", "NOT_A_TOKEN", "--version", extension.version, "--assetIndex", version.assetIndex.id, "--assetsDir", new File(extension.getUserCache(), "assets-" + extension.version).getAbsolutePath()); | ||||||
| 
 | 
 | ||||||
| 		setWorkingDir(new File(getProject().getRootDir(), "run")); | 		setWorkingDir(new File(getProject().getRootDir(), "run")); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -65,8 +65,6 @@ public class RunServerTask extends JavaExec { | ||||||
| 		libs.add(Constants.MINECRAFT_FINAL_JAR.get(extension).getAbsolutePath()); | 		libs.add(Constants.MINECRAFT_FINAL_JAR.get(extension).getAbsolutePath()); | ||||||
| 		classpath(libs); | 		classpath(libs); | ||||||
| 
 | 
 | ||||||
| 		args("--tweakClass", "com.openmodloader.loader.launch.OpenServerTweaker"); |  | ||||||
| 
 |  | ||||||
| 		setWorkingDir(new File(getProject().getRootDir(), "run")); | 		setWorkingDir(new File(getProject().getRootDir(), "run")); | ||||||
| 
 | 
 | ||||||
| 		super.exec(); | 		super.exec(); | ||||||
|  | @ -74,7 +72,7 @@ public class RunServerTask extends JavaExec { | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public String getMain() { | 	public String getMain() { | ||||||
| 		return "net.minecraft.launchwrapper.Launch"; | 		return "com.openmodloader.loader.launch.ServerLauncher"; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
|  |  | ||||||
|  | @ -58,7 +58,6 @@ public class Constants { | ||||||
| 	public static final IDelayed<File> MINECRAFT_LIBS = new DelayedFile(extension -> new File(extension.getUserCache(), extension.version + "-libs")); | 	public static final IDelayed<File> MINECRAFT_LIBS = new DelayedFile(extension -> new File(extension.getUserCache(), extension.version + "-libs")); | ||||||
| 	public static final IDelayed<File> MINECRAFT_NATIVES = new DelayedFile(extension -> new File(extension.getUserCache(), extension.version + "-natives")); | 	public static final IDelayed<File> MINECRAFT_NATIVES = new DelayedFile(extension -> new File(extension.getUserCache(), extension.version + "-natives")); | ||||||
| 	public static final IDelayed<File> MINECRAFT_JSON = new DelayedFile(extension -> new File(extension.getUserCache(), extension.version + "-info.json")); | 	public static final IDelayed<File> MINECRAFT_JSON = new DelayedFile(extension -> new File(extension.getUserCache(), extension.version + "-info.json")); | ||||||
| 	public static final IDelayed<File> REF_MAP = new DelayedFile(extension -> new File(CACHE_FILES, "mixin-refmap.json")); |  | ||||||
| 
 | 
 | ||||||
| 	public static final IDelayed<File> VERSION_MANIFEST = new DelayedFile(extension -> new File(extension.getUserCache(), "version_manifest.json")); | 	public static final IDelayed<File> VERSION_MANIFEST = new DelayedFile(extension -> new File(extension.getUserCache(), "version_manifest.json")); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,75 +0,0 @@ | ||||||
| package net.fabricmc.loom.util.proccessing; |  | ||||||
| 
 |  | ||||||
| import com.google.common.collect.BiMap; |  | ||||||
| import com.google.common.collect.HashBiMap; |  | ||||||
| import net.fabricmc.tinyremapper.TinyUtils; |  | ||||||
| import org.objectweb.asm.commons.Remapper; |  | ||||||
| import org.spongepowered.asm.mixin.extensibility.IRemapper; |  | ||||||
| 
 |  | ||||||
| import java.io.BufferedReader; |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.util.HashMap; |  | ||||||
| import java.util.Map; |  | ||||||
| 
 |  | ||||||
| public class MixinDevRemapper implements IRemapper { |  | ||||||
| 	private final BiMap<String, String> classMap = HashBiMap.create(); |  | ||||||
| 	private final Map<TinyUtils.Mapping, TinyUtils.Mapping> fieldMap = new HashMap<>(); |  | ||||||
| 	private final Map<TinyUtils.Mapping, TinyUtils.Mapping> methodMap = new HashMap<>(); |  | ||||||
| 
 |  | ||||||
| 	private final SimpleClassMapper classMapper = new SimpleClassMapper(classMap); |  | ||||||
| 	private final SimpleClassMapper classUnmapper = new SimpleClassMapper(classMap.inverse()); |  | ||||||
| 
 |  | ||||||
| 	private static class SimpleClassMapper extends Remapper { |  | ||||||
| 		final Map<String, String> classMap; |  | ||||||
| 
 |  | ||||||
| 		public SimpleClassMapper(Map<String, String> map) { |  | ||||||
| 			this.classMap = map; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public String map(String typeName) { |  | ||||||
| 			return this.classMap.getOrDefault(typeName, typeName); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	public void readMapping(BufferedReader reader, String fromM, String toM) throws IOException { |  | ||||||
| 		TinyUtils.read(reader, fromM, toM, classMap::put, fieldMap::put, methodMap::put); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	@Override |  | ||||||
| 	public String mapMethodName(String owner, String name, String desc) { |  | ||||||
| 		TinyUtils.Mapping mapping = methodMap.get(new TinyUtils.Mapping(owner, name, desc)); |  | ||||||
| 		return mapping != null ? mapping.name : name; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	@Override |  | ||||||
| 	public String mapFieldName(String owner, String name, String desc) { |  | ||||||
| 		TinyUtils.Mapping mapping = fieldMap.get(new TinyUtils.Mapping(owner, name, desc)); |  | ||||||
| 		if(mapping == null){ |  | ||||||
| 			//We try again using obfed names |  | ||||||
| 			owner = unmap(owner); |  | ||||||
| 			desc = unmapDesc(desc); |  | ||||||
| 			mapping = fieldMap.get(new TinyUtils.Mapping(owner, name, desc)); |  | ||||||
| 		} |  | ||||||
| 		return mapping != null ? mapping.name : name; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	@Override |  | ||||||
| 	public String map(String typeName) { |  | ||||||
| 		return classMap.getOrDefault(typeName, typeName); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	@Override |  | ||||||
| 	public String unmap(String typeName) { |  | ||||||
| 		return classMap.inverse().getOrDefault(typeName, typeName); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	@Override |  | ||||||
| 	public String mapDesc(String desc) { |  | ||||||
| 		return classMapper.mapDesc(desc); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	@Override |  | ||||||
| 	public String unmapDesc(String desc) { |  | ||||||
| 		return classUnmapper.mapDesc(desc); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -1,317 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright 2016 FabricMC |  | ||||||
|  * |  | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||||
|  * you may not use this file except in compliance with the License. |  | ||||||
|  * You may obtain a copy of the License at |  | ||||||
|  * |  | ||||||
|  *     http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
|  * |  | ||||||
|  * Unless required by applicable law or agreed to in writing, software |  | ||||||
|  * distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
|  * See the License for the specific language governing permissions and |  | ||||||
|  * limitations under the License. |  | ||||||
|  */ |  | ||||||
| package net.fabricmc.loom.util.proccessing; |  | ||||||
| 
 |  | ||||||
| import com.google.common.base.Charsets; |  | ||||||
| import com.google.common.base.Predicate; |  | ||||||
| import com.google.common.io.ByteStreams; |  | ||||||
| import com.google.gson.Gson; |  | ||||||
| import com.google.gson.JsonArray; |  | ||||||
| import com.google.gson.JsonObject; |  | ||||||
| import net.fabricmc.loom.mixin.MixinServiceGradle; |  | ||||||
| import net.minecraft.launchwrapper.Launch; |  | ||||||
| import net.minecraft.launchwrapper.LaunchClassLoader; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| import org.objectweb.asm.*; |  | ||||||
| import org.spongepowered.asm.launch.GlobalProperties; |  | ||||||
| import org.spongepowered.asm.launch.MixinBootstrap; |  | ||||||
| import org.spongepowered.asm.mixin.EnvironmentStateTweaker; |  | ||||||
| import org.spongepowered.asm.mixin.MixinEnvironment; |  | ||||||
| import org.spongepowered.asm.mixin.Mixins; |  | ||||||
| import org.spongepowered.asm.mixin.transformer.MixinTransformer; |  | ||||||
| import org.spongepowered.asm.service.MixinService; |  | ||||||
| import org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper; |  | ||||||
| 
 |  | ||||||
| import javax.annotation.Nonnull; |  | ||||||
| import java.io.*; |  | ||||||
| import java.net.URLClassLoader; |  | ||||||
| import java.nio.file.Files; |  | ||||||
| import java.nio.file.attribute.FileTime; |  | ||||||
| import java.time.Instant; |  | ||||||
| import java.util.*; |  | ||||||
| import java.util.jar.JarEntry; |  | ||||||
| import java.util.jar.JarFile; |  | ||||||
| import java.util.jar.JarInputStream; |  | ||||||
| import java.util.jar.JarOutputStream; |  | ||||||
| import java.util.stream.Collectors; |  | ||||||
| import java.util.zip.ZipEntry; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * The purpose of this class is to provide an utility for baking mixins from |  | ||||||
|  * mods into a JAR file at compile time to make accessing APIs provided by them |  | ||||||
|  * more intuitive in development environment. |  | ||||||
|  */ |  | ||||||
| public class MixinPrebaker { |  | ||||||
| 	private static class DesprinklingFieldVisitor extends FieldVisitor { |  | ||||||
| 		public DesprinklingFieldVisitor(int api, FieldVisitor fv) { |  | ||||||
| 			super(api, fv); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		@Override |  | ||||||
| 		public AnnotationVisitor visitAnnotation(String desc, boolean visible) { |  | ||||||
| 			if (isSprinkledAnnotation(desc)) { |  | ||||||
| 				return null; |  | ||||||
| 			} |  | ||||||
| 			return super.visitAnnotation(desc, visible); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	private static class DesprinklingMethodVisitor extends MethodVisitor { |  | ||||||
| 		public DesprinklingMethodVisitor(int api, MethodVisitor mv) { |  | ||||||
| 			super(api, mv); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		@Override |  | ||||||
| 		public AnnotationVisitor visitAnnotation(String desc, boolean visible) { |  | ||||||
| 			if (isSprinkledAnnotation(desc)) { |  | ||||||
| 				return null; |  | ||||||
| 			} |  | ||||||
| 			return super.visitAnnotation(desc, visible); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	private static class DesprinklingClassVisitor extends ClassVisitor { |  | ||||||
| 		public DesprinklingClassVisitor(int api, ClassVisitor cv) { |  | ||||||
| 			super(api, cv); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		@Override |  | ||||||
| 		public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { |  | ||||||
| 			return new DesprinklingFieldVisitor(Opcodes.ASM5, super.visitField(access, name, desc, signature, value)); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		@Override |  | ||||||
| 		public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { |  | ||||||
| 			return new DesprinklingMethodVisitor(Opcodes.ASM5, super.visitMethod(access, name, desc, signature, exceptions)); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		@Override |  | ||||||
| 		public AnnotationVisitor visitAnnotation(String desc, boolean visible) { |  | ||||||
| 			if (isSprinkledAnnotation(desc)) { |  | ||||||
| 				return null; |  | ||||||
| 			} |  | ||||||
| 			return super.visitAnnotation(desc, visible); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	private static boolean isSprinkledAnnotation(String desc) { |  | ||||||
| 		//System.out.println(desc); |  | ||||||
| 		return desc.startsWith("Lorg/spongepowered/asm/mixin/transformer/meta"); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Term proposed by Mumfrey, don't blame me |  | ||||||
| 	public static byte[] desprinkle(byte[] cls) { |  | ||||||
| 		ClassReader reader = new ClassReader(cls); |  | ||||||
| 		ClassWriter writer = new ClassWriter(0); |  | ||||||
| 
 |  | ||||||
| 		reader.accept(new DesprinklingClassVisitor(Opcodes.ASM5, writer), 0); |  | ||||||
| 		return writer.toByteArray(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	public static final String APPLIED_MIXIN_CONFIGS_FILENAME = ".oml-applied-mixin-configs"; |  | ||||||
| 	public static final String MAPPINGS_FILENAME = ".oml-dev-mappings.tiny"; |  | ||||||
| 
 |  | ||||||
| 	public static Map<String, InputStream> jarFileCache = new HashMap<>(); |  | ||||||
| 
 |  | ||||||
| 	public static void main(String[] args, Project project) throws IOException { |  | ||||||
| 		boolean hasMappingsFile = false; |  | ||||||
| 
 |  | ||||||
| 		if (args.length < 3) { |  | ||||||
| 			System.out.println("usage: MixinPrebaker [-m mapping-file] <input-jar> <output-jar> <mod-jars...>"); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		File mappingsFile = null; |  | ||||||
| 		int argOffset; |  | ||||||
| 		for (argOffset = 0; argOffset < args.length; argOffset++) { |  | ||||||
| 			if ("-m".equals(args[argOffset])) { |  | ||||||
| 				hasMappingsFile = true; |  | ||||||
| 				mappingsFile = new File(args[++argOffset]); |  | ||||||
| 				//TODO this is prob what was handling the mixin remmapping, this may need to be added back |  | ||||||
| 				//FabricMixinBootstrap.setMappingFile(); |  | ||||||
| 			} else { |  | ||||||
| 				break; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 		Set<File> modFiles = new HashSet<>(); |  | ||||||
| 		for (int i = argOffset + 2; i < args.length; i++) { |  | ||||||
| 			modFiles.add(new File(args[i])); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		URLClassLoader ucl = (URLClassLoader) MixinPrebaker.class.getClassLoader(); |  | ||||||
| 		Launch.classLoader = new LaunchClassLoader(ucl.getURLs()); |  | ||||||
| 		Launch.blackboard = new HashMap<>(); |  | ||||||
| 		Launch.blackboard.put(MixinServiceLaunchWrapper.BLACKBOARD_KEY_TWEAKS, Collections.emptyList()); |  | ||||||
| 
 |  | ||||||
| 		List<JsonObject> mods = findModInfo(modFiles); |  | ||||||
| 		System.out.println("Found " + mods.size() + " mods"); |  | ||||||
| 		List<String> mixins = new ArrayList<>(); |  | ||||||
| 		for(JsonObject modObject : mods){ |  | ||||||
| 			mixins.addAll(findMixins(modObject.getAsJsonArray("mixins"))); |  | ||||||
| 			mixins.addAll(findMixins(modObject.getAsJsonArray("clientMixins"))); |  | ||||||
| 			mixins.addAll(findMixins(modObject.getAsJsonArray("serverMixins"))); |  | ||||||
| 		} |  | ||||||
| 		System.out.println("Found " + mixins.size() + " mixins to pre bake"); |  | ||||||
| 
 |  | ||||||
| 		List<String> tweakers = new ArrayList<>(); |  | ||||||
| 		tweakers.add("com.openmodloader.loader.launch.OpenTweaker"); |  | ||||||
| 		GlobalProperties.put("TweakClasses", tweakers); |  | ||||||
| 
 |  | ||||||
| 		MixinBootstrap.init(); |  | ||||||
| 		mixins.forEach(Mixins::addConfiguration); |  | ||||||
| 
 |  | ||||||
| 		MixinServiceGradle.setupModFiles(modFiles, new File(args[argOffset + 0])); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 		EnvironmentStateTweaker tweaker = new EnvironmentStateTweaker(); |  | ||||||
| 		tweaker.getLaunchArguments(); |  | ||||||
| 		tweaker.injectIntoClassLoader(Launch.classLoader); |  | ||||||
| 
 |  | ||||||
| 		//MixinServiceGradle.addMCDeps(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES).getFiles(), tweaker); |  | ||||||
| 
 |  | ||||||
| 		MixinEnvironment mixinEnvironment = MixinEnvironment.getDefaultEnvironment(); |  | ||||||
| 
 |  | ||||||
| 		System.out.println("Loading mappings: " + mappingsFile); |  | ||||||
| 		InputStream mappingStream = new FileInputStream(mappingsFile); |  | ||||||
| 		MixinDevRemapper devRemapper = new MixinDevRemapper(); |  | ||||||
| 		devRemapper.readMapping(new BufferedReader(new InputStreamReader(mappingStream)), "pomf", "mojang"); |  | ||||||
| 		mappingStream.close(); |  | ||||||
| 		mixinEnvironment.getRemappers().add(devRemapper); |  | ||||||
| 
 |  | ||||||
| 		mixinEnvironment.setSide(MixinEnvironment.Side.CLIENT); //TODO have an all side? |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 		MixinTransformer mixinTransformer = GlobalProperties.get(GlobalProperties.Keys.TRANSFORMER); |  | ||||||
| 		if(mixinTransformer == null){ |  | ||||||
| 			MixinService.getService().beginPhase(); |  | ||||||
| 			mixinTransformer = GlobalProperties.get(GlobalProperties.Keys.TRANSFORMER); |  | ||||||
| 		} |  | ||||||
| 		mixinTransformer.audit(mixinEnvironment); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 		try { |  | ||||||
| 			JarInputStream input = new JarInputStream(new FileInputStream(new File(args[argOffset + 0]))); |  | ||||||
| 			JarOutputStream output = new JarOutputStream(new FileOutputStream(new File(args[argOffset + 1]))); |  | ||||||
| 			JarEntry entry; |  | ||||||
| 			while ((entry = input.getNextJarEntry()) != null) { |  | ||||||
| 				if (entry.getName().equals(APPLIED_MIXIN_CONFIGS_FILENAME)) { |  | ||||||
| 					continue; |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				if (hasMappingsFile && entry.getName().equals(MAPPINGS_FILENAME)) { |  | ||||||
| 					continue; |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				if (entry.getName().endsWith(".class")) { |  | ||||||
| 					byte[] classIn = ByteStreams.toByteArray(input); |  | ||||||
| 					String className = entry.getName().substring(0, entry.getName().length() - 6).replace('/', '.'); |  | ||||||
| 					byte[] classOut = mixinTransformer.transformClassBytes(className, className, classIn); |  | ||||||
| 					if (classIn != classOut) { |  | ||||||
| 						System.out.println("Transformed " + className); |  | ||||||
| 						classOut = desprinkle(classOut); |  | ||||||
| 					} |  | ||||||
| 					JarEntry newEntry = new JarEntry(entry.getName()); |  | ||||||
| 					newEntry.setComment(entry.getComment()); |  | ||||||
| 					newEntry.setSize(classOut.length); |  | ||||||
| 					newEntry.setLastModifiedTime(FileTime.from(Instant.now())); |  | ||||||
| 					output.putNextEntry(newEntry); |  | ||||||
| 					output.write(classOut); |  | ||||||
| 				} else { |  | ||||||
| 					output.putNextEntry(entry); |  | ||||||
| 					ByteStreams.copy(input, output); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			output.putNextEntry(new JarEntry(APPLIED_MIXIN_CONFIGS_FILENAME)); |  | ||||||
| 			output.write(String.join("\n", mixins).getBytes(Charsets.UTF_8)); |  | ||||||
| 
 |  | ||||||
| 			if (hasMappingsFile) { |  | ||||||
| 				output.putNextEntry(new JarEntry(MAPPINGS_FILENAME)); |  | ||||||
| 				Files.copy(mappingsFile.toPath(), output); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			input.close(); |  | ||||||
| 			output.close(); |  | ||||||
| 		} catch (IOException e) { |  | ||||||
| 			throw new RuntimeException(e); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	private static List<String> findMixins(JsonArray jsonArray){ |  | ||||||
| 		if(jsonArray == null || jsonArray.size() == 0){ |  | ||||||
| 			return Collections.emptyList(); |  | ||||||
| 		} |  | ||||||
| 		List<String> mixinList = new ArrayList<>(); |  | ||||||
| 		for (int i = 0; i < jsonArray.size(); i++) { |  | ||||||
| 			mixinList.add(jsonArray.get(i).getAsString()); |  | ||||||
| 		} |  | ||||||
| 		return mixinList; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	private static List<JsonObject> findModInfo(Set<File> mods){ |  | ||||||
| 		List<JsonArray> modFiles = mods.stream().map(file -> { |  | ||||||
| 			try { |  | ||||||
| 				JarFile jar = new JarFile(file); |  | ||||||
| 				return readModInfoFromJar(jar); |  | ||||||
| 			} catch (IOException e) { |  | ||||||
| 				throw new RuntimeException("Failed to mod " + file.getName(), e); |  | ||||||
| 			} |  | ||||||
| 		}).filter((Predicate<JsonArray>) Objects::nonNull).collect(Collectors.toList()); |  | ||||||
| 
 |  | ||||||
| 		List<JsonObject> containedMods = new ArrayList<>(); |  | ||||||
| 		for(JsonArray modFile : modFiles){ |  | ||||||
| 			for (int i = 0; i < modFile.size(); i++) { |  | ||||||
| 				containedMods.add(modFile.get(i).getAsJsonObject()); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		return containedMods; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	private static JsonArray readModInfoFromJar(@Nonnull JarFile file) throws IOException { |  | ||||||
| 		Gson gson = new Gson(); |  | ||||||
| 		ZipEntry entry = file.getEntry("mod.json"); |  | ||||||
| 		if (entry == null) |  | ||||||
| 			return null; |  | ||||||
| 
 |  | ||||||
| 		InputStreamReader stream = new InputStreamReader(file.getInputStream(entry)); |  | ||||||
| 		JsonArray jsonArray = gson.fromJson(stream, JsonArray.class); |  | ||||||
| 		stream.close(); |  | ||||||
| 
 |  | ||||||
| 		List<String> mixins = new ArrayList<>(); |  | ||||||
| 		for (int i = 0; i < jsonArray.size(); i++) { |  | ||||||
| 			JsonObject modObject = jsonArray.get(i).getAsJsonObject(); |  | ||||||
| 			mixins.addAll(findMixins(modObject.getAsJsonArray("mixins"))); |  | ||||||
| 			mixins.addAll(findMixins(modObject.getAsJsonArray("clientMixins"))); |  | ||||||
| 			mixins.addAll(findMixins(modObject.getAsJsonArray("serverMixins"))); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		System.out.println("Found: " + mixins.size() + " mixins in " + file.getName()); |  | ||||||
| 
 |  | ||||||
| 		mixins.forEach(s -> { |  | ||||||
| 			ZipEntry entry1 = file.getEntry(s); |  | ||||||
| 			try { |  | ||||||
| 				jarFileCache.put(s, file.getInputStream(entry1)); |  | ||||||
| 			} catch (IOException e) { |  | ||||||
| 				throw new RuntimeException("Failed to load jar", e); |  | ||||||
| 			} |  | ||||||
| 		}); |  | ||||||
| 		return jsonArray; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -1,53 +0,0 @@ | ||||||
| /* |  | ||||||
|  * 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.util.proccessing; |  | ||||||
| 
 |  | ||||||
| import net.fabricmc.loom.LoomGradleExtension; |  | ||||||
| import net.fabricmc.loom.task.ProcessModsTask; |  | ||||||
| import net.fabricmc.loom.util.Constants; |  | ||||||
| import org.gradle.api.Project; |  | ||||||
| 
 |  | ||||||
| import java.io.File; |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.util.List; |  | ||||||
| 
 |  | ||||||
| public class PreBakeMixins { |  | ||||||
| 
 |  | ||||||
| 	public void proccess(Project project, LoomGradleExtension extension, List<File> mods) throws IOException { |  | ||||||
| 		project.getLogger().lifecycle(":Found " + mods.size() + " mods to prebake"); |  | ||||||
| 		String[] args = new String[mods.size() + 4]; |  | ||||||
| 		args[0] = "-m"; |  | ||||||
| 		args[1] = Constants.MAPPINGS_TINY.get(extension).getAbsolutePath(); |  | ||||||
| 		args[2] = Constants.MINECRAFT_MERGED_JAR.get(extension).getAbsolutePath(); |  | ||||||
| 		args[3] = Constants.MINECRAFT_MIXED_JAR.get(extension).getAbsolutePath(); |  | ||||||
| 		for (int i = 0; i < mods.size(); i++) { |  | ||||||
| 			args[i + 4] = mods.get(i).getAbsolutePath(); |  | ||||||
| 		} |  | ||||||
| 		project.getLogger().lifecycle(":preBaking mixins"); |  | ||||||
| 		ProcessModsTask.addFile(Constants.MINECRAFT_MIXED_JAR.get(extension), this); |  | ||||||
| 		MixinPrebaker.main(args, project); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| net.fabricmc.loom.mixin.MixinServiceGradle |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| net.fabricmc.loom.mixin.ObfuscationServiceFabric |  | ||||||
		Loading…
	
		Reference in a new issue