Jar merging + reformat

dev/0.11
modmuss50 2016-08-17 17:38:54 +01:00
parent c03f842227
commit 65e2a76d70
21 changed files with 980 additions and 924 deletions

View File

@ -42,6 +42,7 @@ dependencies {
shade 'com.google.code.gson:gson:2.6.2' shade 'com.google.code.gson:gson:2.6.2'
shade 'commons-io:commons-io:1.4' shade 'commons-io:commons-io:1.4'
shade 'com.google.guava:guava:19.0' shade 'com.google.guava:guava:19.0'
shade 'net.fabricmc:blending-jar:0.1.0'
shade 'net.fabricmc:enigma:0.11.+' shade 'net.fabricmc:enigma:0.11.+'
shade 'org.javassist:javassist:3.+' shade 'org.javassist:javassist:3.+'

View File

@ -24,16 +24,14 @@
package net.fabricmc.loom; package net.fabricmc.loom;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson; import com.google.gson.Gson;
import net.fabricmc.loom.task.DownloadTask; import net.fabricmc.loom.task.DownloadTask;
import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.Constants;
import com.google.common.collect.ImmutableMap;
import net.fabricmc.loom.util.Version; import net.fabricmc.loom.util.Version;
import org.gradle.api.Action;
import org.gradle.api.Plugin; import org.gradle.api.Plugin;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.gradle.api.artifacts.repositories.FlatDirectoryArtifactRepository;
import org.gradle.api.artifacts.repositories.MavenArtifactRepository; import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.plugins.JavaPluginConvention;
@ -42,161 +40,159 @@ import org.gradle.api.tasks.javadoc.Javadoc;
import org.gradle.plugins.ide.eclipse.model.EclipseModel; import org.gradle.plugins.ide.eclipse.model.EclipseModel;
import org.gradle.plugins.ide.idea.model.IdeaModel; import org.gradle.plugins.ide.idea.model.IdeaModel;
import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
public class AbstractPlugin implements Plugin<Project> { public class AbstractPlugin implements Plugin<Project> {
protected Project project; protected Project project;
@Override @Override
public void apply(Project target) { public void apply(Project target) {
this.project = target; this.project = target;
// Apply default plugins // Apply default plugins
project.apply(ImmutableMap.of("plugin", "java")); project.apply(ImmutableMap.of("plugin", "java"));
project.apply(ImmutableMap.of("plugin", "eclipse")); project.apply(ImmutableMap.of("plugin", "eclipse"));
project.apply(ImmutableMap.of("plugin", "idea")); project.apply(ImmutableMap.of("plugin", "idea"));
project.getExtensions().create("minecraft", LoomGradleExtension.class); project.getExtensions().create("minecraft", LoomGradleExtension.class);
// Force add Mojang repository // Force add Mojang repository
addMavenRepo(target, "Mojang", "https://libraries.minecraft.net/"); addMavenRepo(target, "Mojang", "https://libraries.minecraft.net/");
// Minecraft libraries configuration // Minecraft libraries configuration
project.getConfigurations().maybeCreate(Constants.CONFIG_MC_DEPENDENCIES); project.getConfigurations().maybeCreate(Constants.CONFIG_MC_DEPENDENCIES);
project.getConfigurations().maybeCreate(Constants.CONFIG_MC_DEPENDENCIES_CLIENT); project.getConfigurations().maybeCreate(Constants.CONFIG_MC_DEPENDENCIES_CLIENT);
project.getConfigurations().maybeCreate(Constants.CONFIG_NATIVES); project.getConfigurations().maybeCreate(Constants.CONFIG_NATIVES);
// Common libraries extends from client libraries, CONFIG_MC_DEPENDENCIES will contains all MC dependencies // Common libraries extends from client libraries, CONFIG_MC_DEPENDENCIES will contains all MC dependencies
project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES).extendsFrom(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES_CLIENT)); project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES).extendsFrom(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES_CLIENT));
configureIDEs(); configureIDEs();
configureCompile(); configureCompile();
} }
/** /**
* Permit to create a Task instance of the type in the project * Permit to create a Task instance of the type in the project
* *
* @param name The name of the task * @param name The name of the task
* @param type The type of the task that will be used to create an instance * @param type The type of the task that will be used to create an instance
* @return The created task object for the project * @return The created task object for the project
*/ */
public <T extends Task> T makeTask(String name, Class<T> type) { public <T extends Task> T makeTask(String name, Class<T> type) {
return makeTask(project, name, type); return makeTask(project, name, type);
} }
/** /**
* Permit to create a Task instance of the type in a project * Permit to create a Task instance of the type in a project
* *
* @param target The target project * @param target The target project
* @param name The name of the task * @param name The name of the task
* @param type The type of the task that will be used to create an instance * @param type The type of the task that will be used to create an instance
* @return The created task object for the specified project * @return The created task object for the specified project
*/ */
public static <T extends Task> T makeTask(Project target, String name, Class<T> type) { public static <T extends Task> T makeTask(Project target, String name, Class<T> type) {
return target.getTasks().create(name, type); return target.getTasks().create(name, type);
} }
/** /**
* Permit to add a Maven repository to a target project * Permit to add a Maven repository to a target project
* *
* @param target The garget project * @param target The garget project
* @param name The name of the repository * @param name The name of the repository
* @param url The URL of the repository * @param url The URL of the repository
* @return An object containing the name and the URL of the repository that can be modified later * @return An object containing the name and the URL of the repository that can be modified later
*/ */
public MavenArtifactRepository addMavenRepo(Project target, final String name, final String url) { public MavenArtifactRepository addMavenRepo(Project target, final String name, final String url) {
return target.getRepositories().maven(repo -> { return target.getRepositories().maven(repo -> {
repo.setName(name); repo.setName(name);
repo.setUrl(url); repo.setUrl(url);
}); });
} }
/** /**
* Add Minecraft dependencies to IDE dependencies * Add Minecraft dependencies to IDE dependencies
*/ */
protected void configureIDEs() { protected void configureIDEs() {
// IDEA // IDEA
IdeaModel ideaModule = (IdeaModel) project.getExtensions().getByName("idea"); IdeaModel ideaModule = (IdeaModel) project.getExtensions().getByName("idea");
ideaModule.getModule().getExcludeDirs().addAll(project.files(".gradle", "build", ".idea", "out").getFiles()); ideaModule.getModule().getExcludeDirs().addAll(project.files(".gradle", "build", ".idea", "out").getFiles());
ideaModule.getModule().setDownloadJavadoc(true); ideaModule.getModule().setDownloadJavadoc(true);
ideaModule.getModule().setDownloadSources(true); ideaModule.getModule().setDownloadSources(true);
ideaModule.getModule().setInheritOutputDirs(true); ideaModule.getModule().setInheritOutputDirs(true);
ideaModule.getModule().getScopes().get("COMPILE").get("plus").add(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES)); ideaModule.getModule().getScopes().get("COMPILE").get("plus").add(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES));
// ECLIPSE // ECLIPSE
EclipseModel eclipseModule = (EclipseModel) project.getExtensions().getByName("eclipse"); EclipseModel eclipseModule = (EclipseModel) project.getExtensions().getByName("eclipse");
eclipseModule.getClasspath().getPlusConfigurations().add(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES)); eclipseModule.getClasspath().getPlusConfigurations().add(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES));
} }
/** /**
* Add Minecraft dependencies to compile time * Add Minecraft dependencies to compile time
*/ */
protected void configureCompile() { protected void configureCompile() {
JavaPluginConvention javaModule = (JavaPluginConvention) project.getConvention().getPlugins().get("java"); JavaPluginConvention javaModule = (JavaPluginConvention) project.getConvention().getPlugins().get("java");
SourceSet main = javaModule.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME); SourceSet main = javaModule.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME);
SourceSet test = javaModule.getSourceSets().getByName(SourceSet.TEST_SOURCE_SET_NAME); SourceSet test = javaModule.getSourceSets().getByName(SourceSet.TEST_SOURCE_SET_NAME);
main.setCompileClasspath(main.getCompileClasspath().plus(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES))); main.setCompileClasspath(main.getCompileClasspath().plus(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES)));
test.setCompileClasspath(test.getCompileClasspath().plus(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES))); test.setCompileClasspath(test.getCompileClasspath().plus(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES)));
main.setRuntimeClasspath(main.getCompileClasspath().plus(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES))); main.setRuntimeClasspath(main.getCompileClasspath().plus(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES)));
test.setCompileClasspath(test.getCompileClasspath().plus(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES))); test.setCompileClasspath(test.getCompileClasspath().plus(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES)));
Javadoc javadoc = (Javadoc) project.getTasks().getByName(JavaPlugin.JAVADOC_TASK_NAME); Javadoc javadoc = (Javadoc) project.getTasks().getByName(JavaPlugin.JAVADOC_TASK_NAME);
javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath())); javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath()));
project.afterEvaluate(project1 -> { project.afterEvaluate(project1 -> {
LoomGradleExtension extension = project1.getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = project1.getExtensions().getByType(LoomGradleExtension.class);
project1.getRepositories().flatDir(flatDirectoryArtifactRepository -> { project1.getRepositories().flatDir(flatDirectoryArtifactRepository -> {
flatDirectoryArtifactRepository.dir(Constants.CACHE_FILES); flatDirectoryArtifactRepository.dir(Constants.CACHE_FILES);
flatDirectoryArtifactRepository.setName("LoomCacheFiles"); flatDirectoryArtifactRepository.setName("LoomCacheFiles");
}); });
project1.getRepositories().maven(mavenArtifactRepository -> { project1.getRepositories().maven(mavenArtifactRepository -> {
mavenArtifactRepository.setName("FabricMC"); mavenArtifactRepository.setName("FabricMC");
mavenArtifactRepository.setUrl("http://maven.fabricmc.net/"); mavenArtifactRepository.setUrl("http://maven.fabricmc.net/");
}); });
project1.getRepositories().maven(mavenArtifactRepository -> { project1.getRepositories().maven(mavenArtifactRepository -> {
mavenArtifactRepository.setName("SpongePowered"); mavenArtifactRepository.setName("SpongePowered");
mavenArtifactRepository.setUrl("http://repo.spongepowered.org/maven"); 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/");
}); });
project1.getRepositories().mavenCentral(); project1.getRepositories().mavenCentral();
project1.getRepositories().jcenter(); project1.getRepositories().jcenter();
Gson gson = new Gson(); Gson gson = new Gson();
try { try {
DownloadTask.downloadMcJson(extension, project1.getLogger()); DownloadTask.downloadMcJson(extension, project1.getLogger());
Version version = gson.fromJson(new FileReader(Constants.MINECRAFT_JSON.get(extension)), Version.class); Version version = gson.fromJson(new FileReader(Constants.MINECRAFT_JSON.get(extension)), Version.class);
for (Version.Library library : version.libraries) { for (Version.Library library : version.libraries) {
if (library.allowed() && library.getFile() != null) { if (library.allowed() && library.getFile() != null) {
String configName = Constants.CONFIG_MC_DEPENDENCIES; String configName = Constants.CONFIG_MC_DEPENDENCIES;
if (library.name.contains("java3d") || library.name.contains("paulscode") || library.name.contains("lwjgl") || library.name.contains("twitch") || library.name.contains("jinput")) { if (library.name.contains("java3d") || library.name.contains("paulscode") || library.name.contains("lwjgl") || library.name.contains("twitch") || library.name.contains("jinput")) {
configName = Constants.CONFIG_MC_DEPENDENCIES_CLIENT; configName = Constants.CONFIG_MC_DEPENDENCIES_CLIENT;
} }
project1.getDependencies().add(configName, library.getArtifactName()); project1.getDependencies().add(configName, library.getArtifactName());
} }
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
project1.getDependencies().add(Constants.CONFIG_MC_DEPENDENCIES, "net.minecraft:" + Constants.MINECRAFT_CLIENT_MAPPED_JAR.get(extension).getName().replace(".jar", "")); project1.getDependencies().add(Constants.CONFIG_MC_DEPENDENCIES, "net.minecraft:" + Constants.MINECRAFT_MAPPED_JAR.get(extension).getName().replace(".jar", ""));
if(extension.fabricVersion != null && !extension.fabricVersion.isEmpty()){ if (extension.fabricVersion != null && !extension.fabricVersion.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.CONFIG_MC_DEPENDENCIES, "net.fabricmc:fabric-base:" + extension.version + "-" + extension.fabricVersion); project1.getDependencies().add(Constants.CONFIG_MC_DEPENDENCIES, "net.fabricmc:fabric-base:" + extension.version + "-" + extension.fabricVersion);
} }
}); });
}
}
} }

View File

@ -25,7 +25,7 @@
package net.fabricmc.loom; package net.fabricmc.loom;
public class LoomGradleExtension { public class LoomGradleExtension {
public String version; public String version;
public String runDir = "run"; public String runDir = "run";
public String fabricVersion; public String fabricVersion;
} }

View File

@ -24,23 +24,21 @@
package net.fabricmc.loom; package net.fabricmc.loom;
import net.fabricmc.loom.task.DownloadTask; import net.fabricmc.loom.task.*;
import net.fabricmc.loom.task.ExtractNativesTask;
import net.fabricmc.loom.task.GenIdeaProjectTask;
import net.fabricmc.loom.task.MapJarsTask;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.Project; import org.gradle.api.Project;
public class LoomGradlePlugin extends AbstractPlugin { public class LoomGradlePlugin extends AbstractPlugin {
@Override @Override
public void apply(Project target) { public void apply(Project target) {
super.apply(target); super.apply(target);
makeTask("download", DownloadTask.class); makeTask("download", DownloadTask.class);
makeTask("mapJars", MapJarsTask.class).dependsOn("download"); makeTask("mergeJars", MergeJarsTask.class).dependsOn("download");
makeTask("setupFabric", DefaultTask.class).dependsOn("mapJars"); makeTask("mapJars", MapJarsTask.class).dependsOn("mergeJars");
makeTask("setupFabric", DefaultTask.class).dependsOn("mapJars");
makeTask("extractNatives", ExtractNativesTask.class).dependsOn("download"); makeTask("extractNatives", ExtractNativesTask.class).dependsOn("download");
makeTask("genIdeaRuns", GenIdeaProjectTask.class).dependsOn("cleanIdea").dependsOn("idea").dependsOn("extractNatives"); makeTask("genIdeaRuns", GenIdeaProjectTask.class).dependsOn("cleanIdea").dependsOn("idea").dependsOn("extractNatives");
} }
} }

View File

@ -46,111 +46,111 @@ import java.nio.channels.ReadableByteChannel;
*/ */
public class DownloadNewTask extends DefaultTask { public class DownloadNewTask extends DefaultTask {
@Input @Input
private Object output; private Object output;
@OutputFile @OutputFile
private String url; private String url;
private String taskName; private String taskName;
@TaskAction @TaskAction
public void download() throws IOException { public void download() throws IOException {
File outputFile = getProject().file(getOutput()); File outputFile = getProject().file(getOutput());
outputFile.getParentFile().mkdirs(); outputFile.getParentFile().mkdirs();
outputFile.createNewFile(); outputFile.createNewFile();
getLogger().info("Downloading " + getURL()); getLogger().info("Downloading " + getURL());
URL url = new URL(getURL()); URL url = new URL(getURL());
HttpURLConnection connect = (HttpURLConnection) url.openConnection(); HttpURLConnection connect = (HttpURLConnection) url.openConnection();
connect.setRequestProperty("User-Agent", Constants.USER_AGENT); connect.setRequestProperty("User-Agent", Constants.USER_AGENT);
connect.setInstanceFollowRedirects(true); connect.setInstanceFollowRedirects(true);
ProgressLogger progressLogger = ProgressLogger.getProgressFactory(getProject(), getClass().getName()); ProgressLogger progressLogger = ProgressLogger.getProgressFactory(getProject(), getClass().getName());
progressLogger.setDescription("Downloading " + getURL()); progressLogger.setDescription("Downloading " + getURL());
ReadableByteChannel inChannel = new DownloadChannel(Channels.newChannel(connect.getInputStream()), getContentLength(url), progressLogger); ReadableByteChannel inChannel = new DownloadChannel(Channels.newChannel(connect.getInputStream()), getContentLength(url), progressLogger);
FileChannel outChannel = new FileOutputStream(outputFile).getChannel(); FileChannel outChannel = new FileOutputStream(outputFile).getChannel();
outChannel.transferFrom(inChannel, 0, Long.MAX_VALUE); outChannel.transferFrom(inChannel, 0, Long.MAX_VALUE);
outChannel.close(); outChannel.close();
inChannel.close(); inChannel.close();
progressLogger.completed(); progressLogger.completed();
getLogger().info("Download complete"); getLogger().info("Download complete");
} }
private int getContentLength(URL url) { private int getContentLength(URL url) {
HttpURLConnection connection; HttpURLConnection connection;
int contentLength = -1; int contentLength = -1;
try { try {
connection = (HttpURLConnection) url.openConnection(); connection = (HttpURLConnection) url.openConnection();
contentLength = connection.getContentLength(); contentLength = connection.getContentLength();
} catch (Exception e) { } catch (Exception e) {
} }
return contentLength; return contentLength;
} }
public File getOutput() { public File getOutput() {
return getProject().file(output); return getProject().file(output);
} }
public void setOutput(Object output) { public void setOutput(Object output) {
this.output = output; this.output = output;
} }
public String getURL() { public String getURL() {
return url; return url;
} }
public void setURL(String url) { public void setURL(String url) {
this.url = url; this.url = url;
} }
public void setTaskName(String taskName) { public void setTaskName(String taskName) {
this.taskName = taskName; this.taskName = taskName;
} }
public String getTaskName() { public String getTaskName() {
return taskName; return taskName;
} }
class DownloadChannel implements ReadableByteChannel { class DownloadChannel implements ReadableByteChannel {
ProgressLogger logger; ProgressLogger logger;
String formattedSize; String formattedSize;
ReadableByteChannel rbc; ReadableByteChannel rbc;
long totalBytes; long totalBytes;
DownloadChannel(ReadableByteChannel rbc, long expectedSize, ProgressLogger logger) { DownloadChannel(ReadableByteChannel rbc, long expectedSize, ProgressLogger logger) {
this.logger = logger; this.logger = logger;
this.formattedSize = toHumanReadableLength(expectedSize); this.formattedSize = toHumanReadableLength(expectedSize);
this.rbc = rbc; this.rbc = rbc;
} }
public void close() throws IOException { public void close() throws IOException {
rbc.close(); rbc.close();
} }
public boolean isOpen() { public boolean isOpen() {
return rbc.isOpen(); return rbc.isOpen();
} }
public int read(ByteBuffer buffer) throws IOException { public int read(ByteBuffer buffer) throws IOException {
int processedBytes; int processedBytes;
if ((processedBytes = rbc.read(buffer)) > 0) { if ((processedBytes = rbc.read(buffer)) > 0) {
totalBytes += processedBytes; totalBytes += processedBytes;
logger.progress(toHumanReadableLength(totalBytes) + "/" + formattedSize + " downloaded"); logger.progress(toHumanReadableLength(totalBytes) + "/" + formattedSize + " downloaded");
} }
return processedBytes; return processedBytes;
} }
private String toHumanReadableLength(long bytes) { private String toHumanReadableLength(long bytes) {
if (bytes < 1024) { if (bytes < 1024) {
return bytes + " B"; return bytes + " B";
} else if (bytes < 1024 * 1024) { } else if (bytes < 1024 * 1024) {
return (bytes / 1024) + " KB"; return (bytes / 1024) + " KB";
} else if (bytes < 1024 * 1024 * 1024) { } else if (bytes < 1024 * 1024 * 1024) {
return String.format("%.2f MB", bytes / (1024.0 * 1024.0)); return String.format("%.2f MB", bytes / (1024.0 * 1024.0));
} else { } else {
return String.format("%.2f GB", bytes / (1024.0 * 1024.0 * 1024.0)); return String.format("%.2f GB", bytes / (1024.0 * 1024.0 * 1024.0));
} }
} }
} }
} }

View File

@ -24,13 +24,13 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.Version;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Checksum; import net.fabricmc.loom.util.Checksum;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.ManifestVersion; import net.fabricmc.loom.util.ManifestVersion;
import net.fabricmc.loom.util.Version;
import net.fabricmc.loom.util.assets.AssetIndex; import net.fabricmc.loom.util.assets.AssetIndex;
import net.fabricmc.loom.util.assets.AssetObject; import net.fabricmc.loom.util.assets.AssetObject;
import net.fabricmc.loom.util.progress.ProgressLogger; import net.fabricmc.loom.util.progress.ProgressLogger;
@ -44,111 +44,115 @@ import org.gradle.api.tasks.TaskAction;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
public class DownloadTask extends DefaultTask { public class DownloadTask extends DefaultTask {
@TaskAction @TaskAction
public void download() { public void download() {
try { try {
LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class);
downloadMcJson(extension, getLogger()); downloadMcJson(extension, getLogger());
Gson gson = new Gson(); Gson gson = new Gson();
Version version = gson.fromJson(new FileReader(Constants.MINECRAFT_JSON.get(extension)), Version.class); Version version = gson.fromJson(new FileReader(Constants.MINECRAFT_JSON.get(extension)), Version.class);
if (!Constants.MINECRAFT_CLIENT_JAR.get(extension).exists() || !Checksum.equals(Constants.MINECRAFT_CLIENT_JAR.get(extension), version.downloads.get("client").sha1)) { if (!Constants.MINECRAFT_CLIENT_JAR.get(extension).exists() || !Checksum.equals(Constants.MINECRAFT_CLIENT_JAR.get(extension), version.downloads.get("client").sha1)) {
this.getLogger().lifecycle(":downloading client"); this.getLogger().lifecycle(":downloading client");
FileUtils.copyURLToFile(new URL(version.downloads.get("client").url), Constants.MINECRAFT_CLIENT_JAR.get(extension)); FileUtils.copyURLToFile(new URL(version.downloads.get("client").url), Constants.MINECRAFT_CLIENT_JAR.get(extension));
} }
if (Constants.MAPPINGS_ZIP.exists()) { if (!Constants.MINECRAFT_SERVER_JAR.get(extension).exists() || !Checksum.equals(Constants.MINECRAFT_SERVER_JAR.get(extension), version.downloads.get("server").sha1)) {
Constants.MAPPINGS_ZIP.delete(); this.getLogger().lifecycle(":downloading server");
} FileUtils.copyURLToFile(new URL(version.downloads.get("server").url), Constants.MINECRAFT_SERVER_JAR.get(extension));
}
this.getLogger().lifecycle(":downloading mappings"); if (Constants.MAPPINGS_ZIP.exists()) {
FileUtils.copyURLToFile(new URL("https://github.com/FabricMC/pomf/archive/master.zip"), Constants.MAPPINGS_ZIP); Constants.MAPPINGS_ZIP.delete();
}
DependencyHandler dependencyHandler = getProject().getDependencies(); this.getLogger().lifecycle(":downloading mappings");
FileUtils.copyURLToFile(new URL("https://github.com/FabricMC/pomf/archive/master.zip"), Constants.MAPPINGS_ZIP);
if (getProject().getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES).getState() == Configuration.State.UNRESOLVED) { DependencyHandler dependencyHandler = getProject().getDependencies();
for (Version.Library library : version.libraries) {
if (library.allowed() && library.getFile() != null) {
// By default, they are all available on all sides
String configName = Constants.CONFIG_MC_DEPENDENCIES;
if (library.name.contains("java3d") || library.name.contains("paulscode") || library.name.contains("lwjgl") || library.name.contains("twitch") || library.name.contains("jinput")) {
configName = Constants.CONFIG_MC_DEPENDENCIES_CLIENT;
}
dependencyHandler.add(configName, library.getArtifactName());
}
}
}
if (getProject().getConfigurations().getByName(Constants.CONFIG_NATIVES).getState() == Configuration.State.UNRESOLVED) { if (getProject().getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES).getState() == Configuration.State.UNRESOLVED) {
version.libraries.stream().filter(lib -> lib.natives != null).forEach(lib -> dependencyHandler.add(Constants.CONFIG_NATIVES, lib.getArtifactName())); for (Version.Library library : version.libraries) {
} if (library.allowed() && library.getFile() != null) {
// By default, they are all available on all sides
String configName = Constants.CONFIG_MC_DEPENDENCIES;
if (library.name.contains("java3d") || library.name.contains("paulscode") || library.name.contains("lwjgl") || library.name.contains("twitch") || library.name.contains("jinput")) {
configName = Constants.CONFIG_MC_DEPENDENCIES_CLIENT;
}
dependencyHandler.add(configName, library.getArtifactName());
}
}
}
// Force add LaunchWrapper if (getProject().getConfigurations().getByName(Constants.CONFIG_NATIVES).getState() == Configuration.State.UNRESOLVED) {
dependencyHandler.add(Constants.CONFIG_MC_DEPENDENCIES, "net.minecraft:launchwrapper:1.11"); version.libraries.stream().filter(lib -> lib.natives != null).forEach(lib -> dependencyHandler.add(Constants.CONFIG_NATIVES, lib.getArtifactName()));
}
Version.AssetIndex assetIndex = version.assetIndex; // Force add LaunchWrapper
dependencyHandler.add(Constants.CONFIG_MC_DEPENDENCIES, "net.minecraft:launchwrapper:1.11");
File assets = new File(Constants.CACHE_FILES, "assets"); Version.AssetIndex assetIndex = version.assetIndex;
if (!assets.exists()) {
assets.mkdirs();
}
File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.id + ".json"); File assets = new File(Constants.CACHE_FILES, "assets");
if (!assetsInfo.exists() || !Checksum.equals(assetsInfo, assetIndex.sha1)) { if (!assets.exists()) {
this.getLogger().lifecycle(":downloading asset index"); assets.mkdirs();
FileUtils.copyURLToFile(new URL(assetIndex.url), assetsInfo); }
}
ProgressLogger progressLogger = ProgressLogger.getProgressFactory(getProject(), getClass().getName()); File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.id + ".json");
progressLogger.start("Downloading assets...", "assets"); if (!assetsInfo.exists() || !Checksum.equals(assetsInfo, assetIndex.sha1)) {
AssetIndex index = new Gson().fromJson(new FileReader(assetsInfo), AssetIndex.class); this.getLogger().lifecycle(":downloading asset index");
Map<String, AssetObject> parent = index.getFileMap(); FileUtils.copyURLToFile(new URL(assetIndex.url), assetsInfo);
final int totalSize = parent.size(); }
int position = 0;
this.getLogger().lifecycle(":downloading assets...");
for (Map.Entry<String, AssetObject> entry : parent.entrySet()) {
AssetObject object = entry.getValue();
String sha1 = object.getHash();
File file = new File(assets, "objects" + File.separator + sha1.substring(0, 2) + File.separator + sha1);
if (!file.exists() || !Checksum.equals(file, sha1)) {
this.getLogger().debug(":downloading asset " + entry.getKey());
FileUtils.copyURLToFile(new URL(Constants.RESOURCES_BASE + sha1.substring(0, 2) + "/" + sha1), file);
}
String assetName = entry.getKey();
int end = assetName.lastIndexOf("/") + 1;
if (end > 0) {
assetName = assetName.substring(end, assetName.length());
}
progressLogger.progress(assetName + " - " + position + "/" + totalSize + " (" + (int) ((position / (double) totalSize) * 100) + "%) assets downloaded");
position++;
}
progressLogger.completed();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void downloadMcJson(LoomGradleExtension extension, Logger logger) throws IOException { ProgressLogger progressLogger = ProgressLogger.getProgressFactory(getProject(), getClass().getName());
if (!Constants.MINECRAFT_JSON.get(extension).exists()) { progressLogger.start("Downloading assets...", "assets");
logger.lifecycle(":downloading minecraft json"); AssetIndex index = new Gson().fromJson(new FileReader(assetsInfo), AssetIndex.class);
FileUtils.copyURLToFile(new URL("https://launchermeta.mojang.com/mc/game/version_manifest.json"), Constants.VERSION_MANIFEST); Map<String, AssetObject> parent = index.getFileMap();
ManifestVersion mcManifest = new GsonBuilder().create().fromJson(FileUtils.readFileToString(Constants.VERSION_MANIFEST), ManifestVersion.class); final int totalSize = parent.size();
int position = 0;
this.getLogger().lifecycle(":downloading assets...");
for (Map.Entry<String, AssetObject> entry : parent.entrySet()) {
AssetObject object = entry.getValue();
String sha1 = object.getHash();
File file = new File(assets, "objects" + File.separator + sha1.substring(0, 2) + File.separator + sha1);
if (!file.exists() || !Checksum.equals(file, sha1)) {
this.getLogger().debug(":downloading asset " + entry.getKey());
FileUtils.copyURLToFile(new URL(Constants.RESOURCES_BASE + sha1.substring(0, 2) + "/" + sha1), file);
}
String assetName = entry.getKey();
int end = assetName.lastIndexOf("/") + 1;
if (end > 0) {
assetName = assetName.substring(end, assetName.length());
}
progressLogger.progress(assetName + " - " + position + "/" + totalSize + " (" + (int) ((position / (double) totalSize) * 100) + "%) assets downloaded");
position++;
}
progressLogger.completed();
} catch (IOException e) {
e.printStackTrace();
}
}
Optional<ManifestVersion.Versions> optionalVersion = mcManifest.versions.stream().filter(versions -> versions.id.equalsIgnoreCase(extension.version)).findFirst(); public static void downloadMcJson(LoomGradleExtension extension, Logger logger) throws IOException {
if (optionalVersion.isPresent()) { if (!Constants.MINECRAFT_JSON.get(extension).exists()) {
FileUtils.copyURLToFile(new URL(optionalVersion.get().url), Constants.MINECRAFT_JSON.get(extension)); logger.lifecycle(":downloading minecraft json");
} else { FileUtils.copyURLToFile(new URL("https://launchermeta.mojang.com/mc/game/version_manifest.json"), Constants.VERSION_MANIFEST);
logger.info(":failed downloading minecraft json"); ManifestVersion mcManifest = new GsonBuilder().create().fromJson(FileUtils.readFileToString(Constants.VERSION_MANIFEST), ManifestVersion.class);
throw new RuntimeException("Failed downloading Minecraft json");
} Optional<ManifestVersion.Versions> optionalVersion = mcManifest.versions.stream().filter(versions -> versions.id.equalsIgnoreCase(extension.version)).findFirst();
} if (optionalVersion.isPresent()) {
} FileUtils.copyURLToFile(new URL(optionalVersion.get().url), Constants.MINECRAFT_JSON.get(extension));
} else {
logger.info(":failed downloading minecraft json");
throw new RuntimeException("Failed downloading Minecraft json");
}
}
}
} }

View File

@ -33,12 +33,12 @@ import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
public class ExtractNativesTask extends DefaultTask { public class ExtractNativesTask extends DefaultTask {
@TaskAction @TaskAction
public void extractNatives() throws FileNotFoundException { public void extractNatives() throws FileNotFoundException {
if (!Constants.MINECRAFT_NATIVES.exists()) { if (!Constants.MINECRAFT_NATIVES.exists()) {
for (File source : getProject().getConfigurations().getByName(Constants.CONFIG_NATIVES)) { for (File source : getProject().getConfigurations().getByName(Constants.CONFIG_NATIVES)) {
ZipUtil.unpack(source, Constants.MINECRAFT_NATIVES); ZipUtil.unpack(source, Constants.MINECRAFT_NATIVES);
} }
} }
} }
} }

View File

@ -24,11 +24,11 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import com.google.gson.Gson;
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.IdeaRunConfig; import net.fabricmc.loom.util.IdeaRunConfig;
import net.fabricmc.loom.util.Version; import net.fabricmc.loom.util.Version;
import com.google.gson.Gson;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
import org.w3c.dom.Document; import org.w3c.dom.Document;
@ -51,142 +51,142 @@ import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
public class GenIdeaProjectTask extends DefaultTask { public class GenIdeaProjectTask extends DefaultTask {
@TaskAction @TaskAction
public void genIdeaRuns() throws IOException, ParserConfigurationException, SAXException, TransformerException { public void genIdeaRuns() throws IOException, ParserConfigurationException, SAXException, TransformerException {
LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class);
File file = new File(getProject().getName() + ".iml"); File file = new File(getProject().getName() + ".iml");
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(file); Document doc = docBuilder.parse(file);
Node component = null; Node component = null;
NodeList module = doc.getElementsByTagName("module").item(0).getChildNodes(); NodeList module = doc.getElementsByTagName("module").item(0).getChildNodes();
for (int i = 0; i < module.getLength(); i++) { for (int i = 0; i < module.getLength(); i++) {
if (module.item(i).getNodeName().equals("component")) { if (module.item(i).getNodeName().equals("component")) {
component = module.item(i); component = module.item(i);
break; break;
} }
} }
if (component == null) { if (component == null) {
this.getLogger().lifecycle(":failed to generate intellij run configurations"); this.getLogger().lifecycle(":failed to generate intellij run configurations");
return; return;
} }
Node content = null; Node content = null;
NodeList moduleList = component.getChildNodes(); NodeList moduleList = component.getChildNodes();
for (int i = 0; i < moduleList.getLength(); i++) { for (int i = 0; i < moduleList.getLength(); i++) {
if (moduleList.item(i).getNodeName().equals("content")) { if (moduleList.item(i).getNodeName().equals("content")) {
content = moduleList.item(i); content = moduleList.item(i);
} }
} }
if (content == null) { if (content == null) {
this.getLogger().lifecycle(":failed to generate intellij run configurations"); this.getLogger().lifecycle(":failed to generate intellij run configurations");
return; return;
} }
Element sourceFolder = doc.createElement("sourceFolder"); Element sourceFolder = doc.createElement("sourceFolder");
sourceFolder.setAttribute("url", "file://$MODULE_DIR$/minecraft/src/main/java"); sourceFolder.setAttribute("url", "file://$MODULE_DIR$/minecraft/src/main/java");
sourceFolder.setAttribute("isTestSource", "false"); sourceFolder.setAttribute("isTestSource", "false");
content.appendChild(sourceFolder); content.appendChild(sourceFolder);
sourceFolder = doc.createElement("sourceFolder"); sourceFolder = doc.createElement("sourceFolder");
sourceFolder.setAttribute("url", "file://$MODULE_DIR$/minecraft/src/main/resources"); sourceFolder.setAttribute("url", "file://$MODULE_DIR$/minecraft/src/main/resources");
sourceFolder.setAttribute("type", "java-resource"); sourceFolder.setAttribute("type", "java-resource");
content.appendChild(sourceFolder); content.appendChild(sourceFolder);
Gson gson = new Gson(); Gson gson = new Gson();
Version version = gson.fromJson(new FileReader(Constants.MINECRAFT_JSON.get(extension)), Version.class); Version version = gson.fromJson(new FileReader(Constants.MINECRAFT_JSON.get(extension)), Version.class);
for (Version.Library library : version.libraries) { for (Version.Library library : version.libraries) {
if (library.allowed() && library.getFile() != null && library.getFile().exists()) { if (library.allowed() && library.getFile() != null && library.getFile().exists()) {
Element node = doc.createElement("orderEntry"); Element node = doc.createElement("orderEntry");
node.setAttribute("type", "module-library"); node.setAttribute("type", "module-library");
Element libraryElement = doc.createElement("library"); Element libraryElement = doc.createElement("library");
Element classes = doc.createElement("CLASSES"); Element classes = doc.createElement("CLASSES");
Element javadoc = doc.createElement("JAVADOC"); Element javadoc = doc.createElement("JAVADOC");
Element sources = doc.createElement("SOURCES"); Element sources = doc.createElement("SOURCES");
Element root = doc.createElement("root"); Element root = doc.createElement("root");
root.setAttribute("url", "jar://" + library.getFile().getAbsolutePath() + "!/"); root.setAttribute("url", "jar://" + library.getFile().getAbsolutePath() + "!/");
classes.appendChild(root); classes.appendChild(root);
libraryElement.appendChild(classes); libraryElement.appendChild(classes);
libraryElement.appendChild(javadoc); libraryElement.appendChild(javadoc);
libraryElement.appendChild(sources); libraryElement.appendChild(sources);
node.appendChild(libraryElement); node.appendChild(libraryElement);
component.appendChild(node); component.appendChild(node);
} else if (!library.allowed()) { } else if (!library.allowed()) {
this.getLogger().info(":" + library.getFile().getName() + " is not allowed on this os"); this.getLogger().info(":" + library.getFile().getName() + " is not allowed on this os");
} }
} }
Element node = doc.createElement("orderEntry"); Element node = doc.createElement("orderEntry");
node.setAttribute("type", "module-library"); node.setAttribute("type", "module-library");
Element libraryElement = doc.createElement("library"); Element libraryElement = doc.createElement("library");
Element classes = doc.createElement("CLASSES"); Element classes = doc.createElement("CLASSES");
Element javadoc = doc.createElement("JAVADOC"); Element javadoc = doc.createElement("JAVADOC");
Element sources = doc.createElement("SOURCES"); Element sources = doc.createElement("SOURCES");
Element root = doc.createElement("root"); Element root = doc.createElement("root");
root.setAttribute("url", "jar://" + Constants.MINECRAFT_CLIENT_MAPPED_JAR.get(extension).getAbsolutePath() + "!/"); root.setAttribute("url", "jar://" + Constants.MINECRAFT_MAPPED_JAR.get(extension).getAbsolutePath() + "!/");
classes.appendChild(root); classes.appendChild(root);
libraryElement.appendChild(classes); libraryElement.appendChild(classes);
libraryElement.appendChild(javadoc); libraryElement.appendChild(javadoc);
libraryElement.appendChild(sources); libraryElement.appendChild(sources);
node.appendChild(libraryElement); node.appendChild(libraryElement);
component.appendChild(node); component.appendChild(node);
TransformerFactory transformerFactory = TransformerFactory.newInstance(); TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer(); Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc); DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(file); StreamResult result = new StreamResult(file);
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.transform(source, result); transformer.transform(source, result);
file = new File(getProject().getName() + ".iws"); file = new File(getProject().getName() + ".iws");
docFactory = DocumentBuilderFactory.newInstance(); docFactory = DocumentBuilderFactory.newInstance();
docBuilder = docFactory.newDocumentBuilder(); docBuilder = docFactory.newDocumentBuilder();
doc = docBuilder.parse(file); doc = docBuilder.parse(file);
NodeList list = doc.getElementsByTagName("component"); NodeList list = doc.getElementsByTagName("component");
Element runManager = null; Element runManager = null;
for (int i = 0; i < list.getLength(); i++) { for (int i = 0; i < list.getLength(); i++) {
Element element = (Element) list.item(i); Element element = (Element) list.item(i);
if (element.getAttribute("name").equals("RunManager")) { if (element.getAttribute("name").equals("RunManager")) {
runManager = element; runManager = element;
break; break;
} }
} }
if (runManager == null) { if (runManager == null) {
this.getLogger().lifecycle(":failed to generate intellij run configurations"); this.getLogger().lifecycle(":failed to generate intellij run configurations");
return; return;
} }
IdeaRunConfig ideaClient = new IdeaRunConfig(); IdeaRunConfig ideaClient = new IdeaRunConfig();
ideaClient.mainClass = "net.minecraft.launchwrapper.Launch"; ideaClient.mainClass = "net.minecraft.launchwrapper.Launch";
ideaClient.projectName = getProject().getName(); ideaClient.projectName = getProject().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=../.gradle/minecraft/natives/ -Dfabric.development=true"; ideaClient.vmArgs = "-Djava.library.path=../.gradle/minecraft/natives/ -Dfabric.development=true";
ideaClient.programArgs = "--tweakClass net.fabricmc.base.launch.FabricClientTweaker --assetIndex " + version.assetIndex.id + " --assetsDir " + new File(Constants.CACHE_FILES, "assets").getAbsolutePath(); ideaClient.programArgs = "--tweakClass net.fabricmc.base.launch.FabricClientTweaker --assetIndex " + version.assetIndex.id + " --assetsDir " + new File(Constants.CACHE_FILES, "assets").getAbsolutePath();
runManager.appendChild(ideaClient.genRuns(runManager)); runManager.appendChild(ideaClient.genRuns(runManager));
transformerFactory = TransformerFactory.newInstance(); transformerFactory = TransformerFactory.newInstance();
transformer = transformerFactory.newTransformer(); transformer = transformerFactory.newTransformer();
source = new DOMSource(doc); source = new DOMSource(doc);
result = new StreamResult(file); result = new StreamResult(file);
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.transform(source, result); transformer.transform(source, result);
File runDir = new File(Constants.WORKING_DIRECTORY, extension.runDir); File runDir = new File(Constants.WORKING_DIRECTORY, extension.runDir);
if (!runDir.exists()) { if (!runDir.exists()) {
runDir.mkdirs(); runDir.mkdirs();
} }
} }
} }

View File

@ -40,50 +40,46 @@ import java.util.jar.JarFile;
public class MapJarsTask extends DefaultTask { public class MapJarsTask extends DefaultTask {
Deobfuscator deobfuscator; Deobfuscator deobfuscator;
@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_CLIENT_MAPPED_JAR.get(extension).exists()){ this.getLogger().lifecycle(":unpacking mappings");
Constants.MINECRAFT_CLIENT_MAPPED_JAR.get(extension).delete(); if (Constants.MAPPINGS_DIR.exists()) {
} FileUtils.deleteDirectory(Constants.MAPPINGS_DIR);
this.getLogger().lifecycle(":unpacking mappings"); }
if(Constants.MAPPINGS_DIR.exists()){ ZipUtil.unpack(Constants.MAPPINGS_ZIP, Constants.MAPPINGS_DIR);
FileUtils.deleteDirectory(Constants.MAPPINGS_DIR);
}
ZipUtil.unpack(Constants.MAPPINGS_ZIP, Constants.MAPPINGS_DIR);
this.getLogger().lifecycle(":remapping jar"); this.getLogger().lifecycle(":remapping jar");
deobfuscator = new Deobfuscator(new JarFile(Constants.MINECRAFT_CLIENT_JAR.get(extension))); deobfuscator = new Deobfuscator(new JarFile(Constants.MINECRAFT_MERGED_JAR.get(extension)));
this.deobfuscator.setMappings(new MappingsEnigmaReader().read(new File(Constants.MAPPINGS_DIR, "pomf-master" + File.separator + "mappings"))); this.deobfuscator.setMappings(new MappingsEnigmaReader().read(new File(Constants.MAPPINGS_DIR, "pomf-master" + File.separator + "mappings")));
this.deobfuscator.writeJar(Constants.MINECRAFT_CLIENT_MAPPED_JAR.get(extension), new ProgressListener()); this.deobfuscator.writeJar(Constants.MINECRAFT_MAPPED_JAR.get(extension), new ProgressListener());
File tempAssests = new File(Constants.CACHE_FILES, "tempAssets"); File tempAssests = new File(Constants.CACHE_FILES, "tempAssets");
ZipUtil.unpack(Constants.MINECRAFT_CLIENT_JAR.get(extension), tempAssests, name -> { ZipUtil.unpack(Constants.MINECRAFT_CLIENT_JAR.get(extension), tempAssests, name -> {
if (name.startsWith("assets") || name.startsWith("log4j2.xml")) { if (name.startsWith("assets") || name.startsWith("log4j2.xml")) {
return name; return name;
} else { } else {
return null; return null;
} }
}); });
ZipUtil.unpack(Constants.MINECRAFT_CLIENT_MAPPED_JAR.get(extension), tempAssests); ZipUtil.unpack(Constants.MINECRAFT_MAPPED_JAR.get(extension), tempAssests);
ZipUtil.pack(tempAssests, Constants.MINECRAFT_CLIENT_MAPPED_JAR.get(extension)); ZipUtil.pack(tempAssests, Constants.MINECRAFT_MAPPED_JAR.get(extension));
} }
public static class ProgressListener implements Deobfuscator.ProgressListener { public static class ProgressListener implements Deobfuscator.ProgressListener {
@Override @Override
public void init(int i, String s) { public void init(int i, String s) {
} }
@Override @Override
public void onProgress(int i, String s) { public void onProgress(int i, String s) {
}
}
}
}
} }

View File

@ -0,0 +1,59 @@
/*
* 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.task;
import net.fabricmc.blendingjar.JarMerger;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Constants;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class MergeJarsTask extends DefaultTask {
@TaskAction
public void mergeJars() throws IOException {
this.getLogger().lifecycle(":merging jars");
LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class);
FileInputStream client = new FileInputStream(Constants.MINECRAFT_CLIENT_JAR.get(extension));
FileInputStream server = new FileInputStream(Constants.MINECRAFT_SERVER_JAR.get(extension));
FileOutputStream merged = new FileOutputStream(Constants.MINECRAFT_MERGED_JAR.get(extension));
JarMerger jarMerger = new JarMerger(client, server, merged);
jarMerger.merge();
jarMerger.close();
client.close();
server.close();
merged.close();
}
}

View File

@ -32,20 +32,20 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
public class Checksum { public class Checksum {
public static boolean equals(File file, String checksum) { public static boolean equals(File file, String checksum) {
if (file == null) { if (file == null) {
return false; return false;
} }
try { try {
HashCode hash = Files.hash(file, Hashing.sha1()); HashCode hash = Files.hash(file, Hashing.sha1());
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (Byte hashBytes : hash.asBytes()) { for (Byte hashBytes : hash.asBytes()) {
builder.append(Integer.toString((hashBytes & 0xFF) + 0x100, 16).substring(1)); builder.append(Integer.toString((hashBytes & 0xFF) + 0x100, 16).substring(1));
} }
return builder.toString().equals(checksum); return builder.toString().equals(checksum);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
return false; return false;
} }
} }

View File

@ -24,8 +24,8 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
import net.fabricmc.loom.util.delayed.IDelayed;
import net.fabricmc.loom.util.delayed.DelayedFile; import net.fabricmc.loom.util.delayed.DelayedFile;
import net.fabricmc.loom.util.delayed.IDelayed;
import java.io.File; import java.io.File;
import java.net.URL; import java.net.URL;
@ -34,40 +34,42 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class Constants { public class Constants {
public static final File WORKING_DIRECTORY = new File("."); public static final File WORKING_DIRECTORY = new File(".");
public static final File CACHE_FILES = new File(WORKING_DIRECTORY, ".gradle/minecraft"); public static final File CACHE_FILES = new File(WORKING_DIRECTORY, ".gradle/minecraft");
public static final IDelayed<File> MINECRAFT_CLIENT_JAR = new DelayedFile(extension -> new File(CACHE_FILES, extension.version + "-client.jar")); public static final IDelayed<File> MINECRAFT_CLIENT_JAR = new DelayedFile(extension -> new File(CACHE_FILES, extension.version + "-client.jar"));
public static final IDelayed<File> MINECRAFT_CLIENT_MAPPED_JAR = new DelayedFile(extension -> new File(CACHE_FILES, extension.version + "-client-mapped.jar")); public static final IDelayed<File> MINECRAFT_SERVER_JAR = new DelayedFile(extension -> new File(CACHE_FILES, extension.version + "-server.jar"));
public static final IDelayed<File> MINECRAFT_MERGED_JAR = new DelayedFile(extension -> new File(CACHE_FILES, extension.version + "-merged.jar"));
public static final IDelayed<File> MINECRAFT_MAPPED_JAR = new DelayedFile(extension -> new File(CACHE_FILES, extension.version + "-mapped.jar"));
public static final File MAPPINGS_ZIP = new File(CACHE_FILES, "mappings.zip"); public static final File MAPPINGS_ZIP = new File(CACHE_FILES, "mappings.zip");
public static final File MAPPINGS_DIR = new File(CACHE_FILES, "mappings"); public static final File MAPPINGS_DIR = new File(CACHE_FILES, "mappings");
public static final File MINECRAFT_LIBS = new File(CACHE_FILES, "libs"); public static final File MINECRAFT_LIBS = new File(CACHE_FILES, "libs");
public static final File MINECRAFT_NATIVES = new File(CACHE_FILES, "natives"); public static final File MINECRAFT_NATIVES = new File(CACHE_FILES, "natives");
public static final IDelayed<File> MINECRAFT_JSON = new DelayedFile(extension -> new File(CACHE_FILES, extension.version + "-info.json")); public static final IDelayed<File> MINECRAFT_JSON = new DelayedFile(extension -> new File(CACHE_FILES, extension.version + "-info.json"));
public static final File MINECRAFT_ROOT = new File(WORKING_DIRECTORY, "minecraft"); public static final File MINECRAFT_ROOT = new File(WORKING_DIRECTORY, "minecraft");
public static final IDelayed<File> MAPPING_SRG = new DelayedFile(extension -> new File(WORKING_DIRECTORY, "mappings.srg")); public static final IDelayed<File> MAPPING_SRG = new DelayedFile(extension -> new File(WORKING_DIRECTORY, "mappings.srg"));
public static final File VERSION_MANIFEST = new File(CACHE_FILES, "version_manifest.json"); public static final File VERSION_MANIFEST = new File(CACHE_FILES, "version_manifest.json");
public static final String LIBRARIES_BASE = "https://libraries.minecraft.net/"; public static final String LIBRARIES_BASE = "https://libraries.minecraft.net/";
public static final String RESOURCES_BASE = "http://resources.download.minecraft.net/"; public static final String RESOURCES_BASE = "http://resources.download.minecraft.net/";
public static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11"; public static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11";
public static final String CONFIG_NATIVES = "MC_NATIVES"; public static final String CONFIG_NATIVES = "MC_NATIVES";
public static final String CONFIG_MC_DEPENDENCIES = "MC_DEPENDENCIES"; public static final String CONFIG_MC_DEPENDENCIES = "MC_DEPENDENCIES";
public static final String CONFIG_MC_DEPENDENCIES_CLIENT = "MC_DEPENDENCIES_CLIENT"; public static final String CONFIG_MC_DEPENDENCIES_CLIENT = "MC_DEPENDENCIES_CLIENT";
public static final String SYSTEM_ARCH = System.getProperty("os.arch").equals("64") ? "64" : "32"; public static final String SYSTEM_ARCH = System.getProperty("os.arch").equals("64") ? "64" : "32";
public static List<String> getClassPath() { public static List<String> getClassPath() {
URL[] urls = ((URLClassLoader) Constants.class.getClassLoader()).getURLs(); URL[] urls = ((URLClassLoader) Constants.class.getClassLoader()).getURLs();
ArrayList<String> list = new ArrayList<>(); ArrayList<String> list = new ArrayList<>();
for (URL url : urls) { for (URL url : urls) {
list.add(url.getPath()); list.add(url.getPath());
} }
return list; return list;
} }
} }

View File

@ -36,42 +36,42 @@ import java.io.IOException;
import java.util.Map; import java.util.Map;
public class IdeaRunConfig { public class IdeaRunConfig {
public String configName; public String configName;
public String projectName; public String projectName;
public String mainClass; public String mainClass;
public String runDir; public String runDir;
public String vmArgs; public String vmArgs;
public String programArgs; public String programArgs;
public Element genRuns(Element doc) throws IOException, ParserConfigurationException, TransformerException { public Element genRuns(Element doc) throws IOException, ParserConfigurationException, TransformerException {
Element root = this.addXml(doc, "component", ImmutableMap.of("name", "ProjectRunConfigurationManager")); Element root = this.addXml(doc, "component", ImmutableMap.of("name", "ProjectRunConfigurationManager"));
root = addXml(root, "configuration", ImmutableMap.of("default", "false", "name", configName, "type", "Application", "factoryName", "Application")); root = addXml(root, "configuration", ImmutableMap.of("default", "false", "name", configName, "type", "Application", "factoryName", "Application"));
this.addXml(root, "module", ImmutableMap.of("name", projectName)); this.addXml(root, "module", ImmutableMap.of("name", projectName));
this.addXml(root, "option", ImmutableMap.of("name", "MAIN_CLASS_NAME", "value", mainClass)); this.addXml(root, "option", ImmutableMap.of("name", "MAIN_CLASS_NAME", "value", mainClass));
this.addXml(root, "option", ImmutableMap.of("name", "WORKING_DIRECTORY", "value", runDir)); this.addXml(root, "option", ImmutableMap.of("name", "WORKING_DIRECTORY", "value", runDir));
if (!Strings.isNullOrEmpty(vmArgs)) { if (!Strings.isNullOrEmpty(vmArgs)) {
this.addXml(root, "option", ImmutableMap.of("name", "VM_PARAMETERS", "value", vmArgs)); this.addXml(root, "option", ImmutableMap.of("name", "VM_PARAMETERS", "value", vmArgs));
} }
if (!Strings.isNullOrEmpty(programArgs)) { if (!Strings.isNullOrEmpty(programArgs)) {
this.addXml(root, "option", ImmutableMap.of("name", "PROGRAM_PARAMETERS", "value", programArgs)); this.addXml(root, "option", ImmutableMap.of("name", "PROGRAM_PARAMETERS", "value", programArgs));
} }
return root; return root;
} }
public Element addXml(Node parent, String name, Map<String, String> values) { public Element addXml(Node parent, String name, Map<String, String> values) {
Document doc = parent.getOwnerDocument(); Document doc = parent.getOwnerDocument();
if (doc == null) { if (doc == null) {
doc = (Document) parent; doc = (Document) parent;
} }
Element e = doc.createElement(name); Element e = doc.createElement(name);
for (Map.Entry<String, String> entry : values.entrySet()) { for (Map.Entry<String, String> entry : values.entrySet()) {
e.setAttribute(entry.getKey(), entry.getValue()); e.setAttribute(entry.getKey(), entry.getValue());
} }
parent.appendChild(e); parent.appendChild(e);
return e; return e;
} }
} }

View File

@ -28,9 +28,9 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ManifestVersion { public class ManifestVersion {
public List<Versions> versions = new ArrayList<>(); public List<Versions> versions = new ArrayList<>();
public static class Versions { public static class Versions {
public String id, url; public String id, url;
} }
} }

View File

@ -25,26 +25,26 @@
package net.fabricmc.loom.util; package net.fabricmc.loom.util;
public class OperatingSystem { public class OperatingSystem {
public static String getOS() { public static String getOS() {
String osName = System.getProperty("os.name").toLowerCase(); String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("win")) { if (osName.contains("win")) {
return "windows"; return "windows";
} else if (osName.contains("mac")) { } else if (osName.contains("mac")) {
return "osx"; return "osx";
} else { } else {
return "linux"; return "linux";
} }
} }
public static String getArch() { public static String getArch() {
if (is64Bit()) { if (is64Bit()) {
return "64"; return "64";
} else { } else {
return "32"; return "32";
} }
} }
public static boolean is64Bit() { public static boolean is64Bit() {
return System.getProperty("sun.arch.data.model").contains("64"); return System.getProperty("sun.arch.data.model").contains("64");
} }
} }

View File

@ -31,129 +31,129 @@ import java.util.List;
import java.util.Map; import java.util.Map;
public class Version { public class Version {
public List<Library> libraries; public List<Library> libraries;
public Map<String, Downloads> downloads; public Map<String, Downloads> downloads;
public AssetIndex assetIndex; public AssetIndex assetIndex;
public class Downloads { public class Downloads {
public String url; public String url;
public String sha1; public String sha1;
} }
public class AssetIndex { public class AssetIndex {
public String id; public String id;
public String sha1; public String sha1;
public String url; public String url;
} }
public class Library { public class Library {
public String name; public String name;
public JsonObject natives; public JsonObject natives;
public JsonObject downloads; public JsonObject downloads;
private Artifact artifact; private Artifact artifact;
public Rule[] rules; public Rule[] rules;
public String getURL() { public String getURL() {
String path; String path;
String[] parts = this.name.split(":", 3); String[] parts = this.name.split(":", 3);
path = parts[0].replace(".", "/") + "/" + parts[1] + "/" + parts[2] + "/" + parts[1] + "-" + parts[2] + getClassifier() + ".jar"; path = parts[0].replace(".", "/") + "/" + parts[1] + "/" + parts[2] + "/" + parts[1] + "-" + parts[2] + getClassifier() + ".jar";
return Constants.LIBRARIES_BASE + path; return Constants.LIBRARIES_BASE + path;
} }
public File getFile() { public File getFile() {
String[] parts = this.name.split(":", 3); String[] parts = this.name.split(":", 3);
return new File(Constants.MINECRAFT_LIBS, parts[0].replace(".", File.separator) + File.separator + parts[1] + File.separator + parts[2] + File.separator + parts[1] + "-" + parts[2] + getClassifier() + ".jar"); return new File(Constants.MINECRAFT_LIBS, parts[0].replace(".", File.separator) + File.separator + parts[1] + File.separator + parts[2] + File.separator + parts[1] + "-" + parts[2] + getClassifier() + ".jar");
} }
public String getSha1() { public String getSha1() {
if (this.downloads == null) { if (this.downloads == null) {
return ""; return "";
} else if (this.downloads.getAsJsonObject("artifact") == null) { } else if (this.downloads.getAsJsonObject("artifact") == null) {
return ""; return "";
} else if (this.downloads.getAsJsonObject("artifact").get("sha1") == null) { } else if (this.downloads.getAsJsonObject("artifact").get("sha1") == null) {
return ""; return "";
} else { } else {
return this.downloads.getAsJsonObject("artifact").get("sha1").getAsString(); return this.downloads.getAsJsonObject("artifact").get("sha1").getAsString();
} }
} }
public String getClassifier() { public String getClassifier() {
if (natives == null) { if (natives == null) {
return ""; return "";
} else { } else {
return "-" + natives.get(OperatingSystem.getOS().replace("${arch}", OperatingSystem.getArch())).getAsString().replace("\"", ""); return "-" + natives.get(OperatingSystem.getOS().replace("${arch}", OperatingSystem.getArch())).getAsString().replace("\"", "");
} }
} }
public boolean allowed() { public boolean allowed() {
if (this.rules == null || this.rules.length <= 0) { if (this.rules == null || this.rules.length <= 0) {
return true; return true;
} }
boolean success = false; boolean success = false;
for (Rule rule : this.rules) { for (Rule rule : this.rules) {
if (rule.os != null && rule.os.name != null) { if (rule.os != null && rule.os.name != null) {
if (rule.os.name.equalsIgnoreCase(OperatingSystem.getOS())) { if (rule.os.name.equalsIgnoreCase(OperatingSystem.getOS())) {
return rule.action.equalsIgnoreCase("allow"); return rule.action.equalsIgnoreCase("allow");
} }
} else { } else {
success = rule.action.equalsIgnoreCase("allow"); success = rule.action.equalsIgnoreCase("allow");
} }
} }
return success; return success;
} }
public String getArtifactName() { public String getArtifactName() {
if (artifact == null) { if (artifact == null) {
artifact = new Artifact(name); artifact = new Artifact(name);
} }
return artifact.getArtifact(natives == null ? artifact.getClassifier() : natives.get(OperatingSystem.getOS()).getAsString()); return artifact.getArtifact(natives == null ? artifact.getClassifier() : natives.get(OperatingSystem.getOS()).getAsString());
} }
private class Artifact { private class Artifact {
private final String domain, name, version, classifier, ext; private final String domain, name, version, classifier, ext;
public Artifact(String name) { public Artifact(String name) {
String[] splitedArtifact = name.split(":"); String[] splitedArtifact = name.split(":");
int idx = splitedArtifact[splitedArtifact.length - 1].indexOf('@'); int idx = splitedArtifact[splitedArtifact.length - 1].indexOf('@');
if (idx != -1) { if (idx != -1) {
ext = splitedArtifact[splitedArtifact.length - 1].substring(idx + 1); ext = splitedArtifact[splitedArtifact.length - 1].substring(idx + 1);
splitedArtifact[splitedArtifact.length - 1] = splitedArtifact[splitedArtifact.length - 1].substring(0, idx); splitedArtifact[splitedArtifact.length - 1] = splitedArtifact[splitedArtifact.length - 1].substring(0, idx);
} else { } else {
ext = "jar"; ext = "jar";
} }
this.domain = splitedArtifact[0]; this.domain = splitedArtifact[0];
this.name = splitedArtifact[1]; this.name = splitedArtifact[1];
this.version = splitedArtifact[2]; this.version = splitedArtifact[2];
this.classifier = splitedArtifact.length > 3 ? splitedArtifact[3] : null; this.classifier = splitedArtifact.length > 3 ? splitedArtifact[3] : null;
} }
public String getArtifact(String classifier) { public String getArtifact(String classifier) {
String ret = domain + ":" + name + ":" + version; String ret = domain + ":" + name + ":" + version;
if (classifier != null && classifier.indexOf('$') > -1) { if (classifier != null && classifier.indexOf('$') > -1) {
classifier = classifier.replace("${arch}", Constants.SYSTEM_ARCH); classifier = classifier.replace("${arch}", Constants.SYSTEM_ARCH);
} }
if (classifier != null) { if (classifier != null) {
ret += ":" + classifier; ret += ":" + classifier;
} }
if (!"jar".equals(ext)) { if (!"jar".equals(ext)) {
ret += "@" + ext; ret += "@" + ext;
} }
return ret; return ret;
} }
public String getClassifier() { public String getClassifier() {
return classifier; return classifier;
} }
} }
} }
private class Rule { private class Rule {
public String action; public String action;
public OS os; public OS os;
private class OS { private class OS {
String name; String name;
} }
} }
} }

View File

@ -30,22 +30,22 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
public class AssetIndex { public class AssetIndex {
private final Map<String, AssetObject> objects; private final Map<String, AssetObject> objects;
private boolean virtual; private boolean virtual;
public AssetIndex() { public AssetIndex() {
this.objects = new LinkedHashMap<>(); this.objects = new LinkedHashMap<>();
} }
public Map<String, AssetObject> getFileMap() { public Map<String, AssetObject> getFileMap() {
return this.objects; return this.objects;
} }
public Set<AssetObject> getUniqueObjects() { public Set<AssetObject> getUniqueObjects() {
return new HashSet<>(this.objects.values()); return new HashSet<>(this.objects.values());
} }
public boolean isVirtual() { public boolean isVirtual() {
return this.virtual; return this.virtual;
} }
} }

View File

@ -25,33 +25,33 @@
package net.fabricmc.loom.util.assets; package net.fabricmc.loom.util.assets;
public class AssetObject { public class AssetObject {
private String hash; private String hash;
private long size; private long size;
public String getHash() { public String getHash() {
return this.hash; return this.hash;
} }
public long getSize() { public long getSize() {
return this.size; return this.size;
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) { if (this == o) {
return true; return true;
} else if ((o == null) || (getClass() != o.getClass())) { } else if ((o == null) || (getClass() != o.getClass())) {
return false; return false;
} else { } else {
AssetObject that = (AssetObject) o; AssetObject that = (AssetObject) o;
return this.size == that.size && this.hash.equals(that.hash); return this.size == that.size && this.hash.equals(that.hash);
} }
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = this.hash.hashCode(); int result = this.hash.hashCode();
result = 31 * result + (int) (this.size ^ this.size >>> 32); result = 31 * result + (int) (this.size ^ this.size >>> 32);
return result; return result;
} }
} }

View File

@ -30,18 +30,18 @@ import java.io.File;
import java.util.function.Function; import java.util.function.Function;
public class DelayedFile implements IDelayed<File> { public class DelayedFile implements IDelayed<File> {
private File file; private File file;
private Function<LoomGradleExtension, File> function; private Function<LoomGradleExtension, File> function;
public DelayedFile(Function<LoomGradleExtension, File> function) { public DelayedFile(Function<LoomGradleExtension, File> function) {
this.function = function; this.function = function;
} }
@Override @Override
public File get(LoomGradleExtension extension) { public File get(LoomGradleExtension extension) {
if (this.file == null) { if (this.file == null) {
this.file = this.function.apply(extension); this.file = this.function.apply(extension);
} }
return this.file; return this.file;
} }
} }

View File

@ -27,5 +27,5 @@ package net.fabricmc.loom.util.delayed;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
public interface IDelayed<T> { public interface IDelayed<T> {
T get(LoomGradleExtension extension); T get(LoomGradleExtension extension);
} }

View File

@ -33,198 +33,198 @@ import java.lang.reflect.Method;
* Wrapper to ProgressLogger internal API * Wrapper to ProgressLogger internal API
*/ */
public class ProgressLogger { public class ProgressLogger {
private final Object logger; private final Object logger;
private final Method getDescription, setDescription, getShortDescription, setShortDescription, getLoggingHeader, setLoggingHeader, start, started, startedArg, progress, completed, completedArg; private final Method getDescription, setDescription, getShortDescription, setShortDescription, getLoggingHeader, setLoggingHeader, start, started, startedArg, progress, completed, completedArg;
private ProgressLogger(Object logger) { private ProgressLogger(Object logger) {
this.logger = logger; this.logger = logger;
this.getDescription = getMethod("getDescription"); this.getDescription = getMethod("getDescription");
this.setDescription = getMethod("setDescription", String.class); this.setDescription = getMethod("setDescription", String.class);
this.getShortDescription = getMethod("getShortDescription"); this.getShortDescription = getMethod("getShortDescription");
this.setShortDescription = getMethod("setShortDescription", String.class); this.setShortDescription = getMethod("setShortDescription", String.class);
this.getLoggingHeader = getMethod("getLoggingHeader"); this.getLoggingHeader = getMethod("getLoggingHeader");
this.setLoggingHeader = getMethod("setLoggingHeader", String.class); this.setLoggingHeader = getMethod("setLoggingHeader", String.class);
this.start = getMethod("start", String.class, String.class); this.start = getMethod("start", String.class, String.class);
this.started = getMethod("started"); this.started = getMethod("started");
this.startedArg = getMethod("started", String.class); this.startedArg = getMethod("started", String.class);
this.progress = getMethod("progress", String.class); this.progress = getMethod("progress", String.class);
this.completed = getMethod("completed"); this.completed = getMethod("completed");
this.completedArg = getMethod("completed", String.class); this.completedArg = getMethod("completed", String.class);
} }
private static Class<?> getFactoryClass() { private static Class<?> getFactoryClass() {
Class<?> progressLoggerFactoryClass = null; Class<?> progressLoggerFactoryClass = null;
try { try {
//Gradle 2.14 and higher //Gradle 2.14 and higher
progressLoggerFactoryClass = Class.forName("org.gradle.internal.logging.progress.ProgressLoggerFactory"); progressLoggerFactoryClass = Class.forName("org.gradle.internal.logging.progress.ProgressLoggerFactory");
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
//prior to Gradle 2.14 //prior to Gradle 2.14
try { try {
progressLoggerFactoryClass = Class.forName("org.gradle.logging.ProgressLoggerFactory"); progressLoggerFactoryClass = Class.forName("org.gradle.logging.ProgressLoggerFactory");
} catch (ClassNotFoundException e1) { } catch (ClassNotFoundException e1) {
// Unsupported Gradle version // Unsupported Gradle version
} }
} }
return progressLoggerFactoryClass; return progressLoggerFactoryClass;
} }
private Method getMethod(String methodName, Class<?>... args) { private Method getMethod(String methodName, Class<?>... args) {
if (logger != null) { if (logger != null) {
try { try {
return logger.getClass().getMethod(methodName, args); return logger.getClass().getMethod(methodName, args);
} catch (NoSuchMethodException ignored) { } catch (NoSuchMethodException ignored) {
} }
} }
return null; return null;
} }
private Object invoke(Method method, Object... args) { private Object invoke(Method method, Object... args) {
if (logger != null) { if (logger != null) {
try { try {
method.setAccessible(true); method.setAccessible(true);
return method.invoke(logger, args); return method.invoke(logger, args);
} catch (IllegalAccessException | InvocationTargetException ignored) { } catch (IllegalAccessException | InvocationTargetException ignored) {
} }
} }
return null; return null;
} }
/** /**
* Get a Progress logger from the Gradle internal API * Get a Progress logger from the Gradle internal API
* *
* @param project The project * @param project The project
* @param category The logger category * @param category The logger category
* @return In any case a progress logger * @return In any case a progress logger
*/ */
public static ProgressLogger getProgressFactory(Project project, String category) { public static ProgressLogger getProgressFactory(Project project, String category) {
try { try {
Method getServices = project.getClass().getMethod("getServices"); Method getServices = project.getClass().getMethod("getServices");
Object serviceFactory = getServices.invoke(project); Object serviceFactory = getServices.invoke(project);
Method get = serviceFactory.getClass().getMethod("get", Class.class); Method get = serviceFactory.getClass().getMethod("get", Class.class);
Object progressLoggerFactory = get.invoke(serviceFactory, getFactoryClass()); Object progressLoggerFactory = get.invoke(serviceFactory, getFactoryClass());
Method newOperation = progressLoggerFactory.getClass().getMethod("newOperation", String.class); Method newOperation = progressLoggerFactory.getClass().getMethod("newOperation", String.class);
return new ProgressLogger(newOperation.invoke(progressLoggerFactory, category)); return new ProgressLogger(newOperation.invoke(progressLoggerFactory, category));
} catch (Exception e) { } catch (Exception e) {
project.getLogger().error("Unable to get progress logger. Download progress will not be displayed."); project.getLogger().error("Unable to get progress logger. Download progress will not be displayed.");
return new ProgressLogger(null); return new ProgressLogger(null);
} }
} }
/** /**
* Returns the description of the operation. * Returns the description of the operation.
* *
* @return the description, must not be empty. * @return the description, must not be empty.
*/ */
public String getDescription() { public String getDescription() {
return (String) invoke(getDescription); return (String) invoke(getDescription);
} }
/** /**
* <p>Sets the description of the operation. This should be a full, stand-alone description of the operation. * <p>Sets the description of the operation. This should be a full, stand-alone description of the operation.
* <p> * <p>
* <p>This must be called before {@link #started()}. * <p>This must be called before {@link #started()}.
* *
* @param description The description. * @param description The description.
*/ */
public ProgressLogger setDescription(String description) { public ProgressLogger setDescription(String description) {
invoke(setDescription, description); invoke(setDescription, description);
return this; return this;
} }
/** /**
* Returns the short description of the operation. This is used in place of the full description when display space is limited. * Returns the short description of the operation. This is used in place of the full description when display space is limited.
* *
* @return The short description, must not be empty. * @return The short description, must not be empty.
*/ */
public String getShortDescription() { public String getShortDescription() {
return (String) invoke(getShortDescription); return (String) invoke(getShortDescription);
} }
/** /**
* <p>Sets the short description of the operation. This is used in place of the full description when display space is limited. * <p>Sets the short description of the operation. This is used in place of the full description when display space is limited.
* <p> * <p>
* <p>This must be called before {@link #started()} * <p>This must be called before {@link #started()}
* *
* @param description The short description. * @param description The short description.
*/ */
public ProgressLogger setShortDescription(String description) { public ProgressLogger setShortDescription(String description) {
invoke(setShortDescription, description); invoke(setShortDescription, description);
return this; return this;
} }
/** /**
* <p>Returns the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually * <p>Returns the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually
* also logged at the end of the operation, along with the final status message. Defaults to null. * also logged at the end of the operation, along with the final status message. Defaults to null.
* <p> * <p>
* <p>If not specified, no logging header is logged. * <p>If not specified, no logging header is logged.
* *
* @return The logging header, possibly empty. * @return The logging header, possibly empty.
*/ */
public String getLoggingHeader() { public String getLoggingHeader() {
return (String) invoke(getLoggingHeader); return (String) invoke(getLoggingHeader);
} }
/** /**
* <p>Sets the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually * <p>Sets the logging header for the operation. This is logged before any other log messages for this operation are logged. It is usually
* also logged at the end of the operation, along with the final status message. Defaults to null. * also logged at the end of the operation, along with the final status message. Defaults to null.
* *
* @param header The header. May be empty or null. * @param header The header. May be empty or null.
*/ */
public ProgressLogger setLoggingHeader(String header) { public ProgressLogger setLoggingHeader(String header) {
invoke(setLoggingHeader, header); invoke(setLoggingHeader, header);
return this; return this;
} }
/** /**
* Convenience method that sets descriptions and logs started() event. * Convenience method that sets descriptions and logs started() event.
* *
* @return this logger instance * @return this logger instance
*/ */
public ProgressLogger start(String description, String shortDescription) { public ProgressLogger start(String description, String shortDescription) {
invoke(start, description, shortDescription); invoke(start, description, shortDescription);
return this; return this;
} }
/** /**
* Logs the start of the operation, with no initial status. * Logs the start of the operation, with no initial status.
*/ */
public void started() { public void started() {
invoke(started); invoke(started);
} }
/** /**
* Logs the start of the operation, with the given status. * Logs the start of the operation, with the given status.
* *
* @param status The initial status message. Can be null or empty. * @param status The initial status message. Can be null or empty.
*/ */
public void started(String status) { public void started(String status) {
invoke(started, status); invoke(started, status);
} }
/** /**
* Logs some progress, indicated by a new status. * Logs some progress, indicated by a new status.
* *
* @param status The new status message. Can be null or empty. * @param status The new status message. Can be null or empty.
*/ */
public void progress(String status) { public void progress(String status) {
invoke(progress, status); invoke(progress, status);
} }
/** /**
* Logs the completion of the operation, with no final status * Logs the completion of the operation, with no final status
*/ */
public void completed() { public void completed() {
invoke(completed); invoke(completed);
} }
/** /**
* Logs the completion of the operation, with a final status. This is generally logged along with the description. * Logs the completion of the operation, with a final status. This is generally logged along with the description.
* *
* @param status The final status message. Can be null or empty. * @param status The final status message. Can be null or empty.
*/ */
public void completed(String status) { public void completed(String status) {
invoke(completed, status); invoke(completed, status);
} }
} }