recreate repo

dev/0.11
asiekierka 2016-08-15 12:22:14 +02:00
commit 7efa7780fe
29 changed files with 1613 additions and 0 deletions

15
.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
/.idea
/work
/tools
/build
/.gradle
*.log
*.reject
/run/
*.iml
*.ipr
*.iws
/out
/classes/

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 ChorusMC
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.

5
README.md Normal file
View File

@ -0,0 +1,5 @@
# ChorusGradle
Gradle plugin for Chorus
run : bash gradlew setupChorus genIdeaRuns

62
build.gradle Normal file
View File

@ -0,0 +1,62 @@
apply plugin: 'java'
apply plugin: 'groovy'
apply plugin: 'maven'
apply plugin: 'maven-publish'
apply plugin: 'idea'
group = 'chorusmc.gradle'
version = '0.0.1'
sourceCompatibility = targetCompatibility = '1.8'
if (System.getenv().BUILD_NUMBER) {
version = version + "." + "${System.getenv().BUILD_NUMBER}"
}
repositories {
mavenCentral()
flatDir {
dirs 'libs'
}
ivy {
name "Enigma-Temporary"
artifactPattern "http://modmuss50.me:8080/job/Enigma-Asie/lastSuccessfulBuild/artifact/build/libs/[module]-[revision]-[classifier].[ext]"
}
}
configurations {
deployerJars
shade
compile.extendsFrom shade
}
dependencies {
compile gradleApi()
shade 'org.zeroturnaround:zt-zip:1.9'
compile 'org.slf4j:slf4j-api:1.7.21'
compile 'org.slf4j:slf4j-simple:1.7.21'
shade 'com.google.code.gson:gson:2.6.2'
shade 'com.googlecode.java-diff-utils:diffutils:1.3.0'
shade 'com.cloudbees:diff4j:1.2'
shade 'commons-io:commons-io:1.4'
shade 'com.google.guava:guava-jdk5:17.0'
shade 'org.ow2.asm:asm-debug-all:5.0.3'
shade 'com.google.guava:guava:19.0'
shade name: "enigma", version: "0.11.0.6", classifier: "all"
}
sourceSets {
main.compileClasspath += configurations.shade;
main.runtimeClasspath += configurations.shade;
test.compileClasspath += configurations.shade;
test.runtimeClasspath += configurations.shade;
}
jar {
configurations.shade.each { dep ->
from(project.zipTree(dep)) {
exclude 'META-INF', 'META-INF/**'
}
}
}
//TODO maven uploading

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Wed Jun 22 18:29:49 CEST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip

164
gradlew vendored Normal file
View File

@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
gradlew.bat vendored Normal file
View File

@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

2
settings.gradle Normal file
View File

@ -0,0 +1,2 @@
rootProject.name = 'ChorusGradle'

View File

@ -0,0 +1,118 @@
package chorusmc.gradle;
import chorusmc.gradle.util.Constants;
import com.google.common.collect.ImmutableMap;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.gradle.plugins.ide.eclipse.model.EclipseModel;
import org.gradle.plugins.ide.idea.model.IdeaModel;
public class AbstractPlugin implements Plugin<Project> {
protected Project project;
@Override
public void apply(Project target) {
this.project = target;
// Apply default plugins
project.apply(ImmutableMap.of("plugin", "java"));
project.apply(ImmutableMap.of("plugin", "eclipse"));
project.apply(ImmutableMap.of("plugin", "idea"));
project.getExtensions().create("minecraft", ChorusGradleExtension.class);
// Force add Mojang repository
addMavenRepo(target, "Mojang", "https://libraries.minecraft.net/");
// Minecraft libraries configuration
project.getConfigurations().maybeCreate(Constants.CONFIG_MC_DEPENDENCIES);
project.getConfigurations().maybeCreate(Constants.CONFIG_MC_DEPENDENCIES_CLIENT);
project.getConfigurations().maybeCreate(Constants.CONFIG_NATIVES);
// 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));
configureIDEs();
configureCompile();
}
/**
* Permit to create a Task instance of the type in the project
*
* @param name The name of the task
* @param type The type of the task that will be used to create an instance
* @return The created task object for the project
*/
public <T extends Task> T makeTask(String name, Class<T> type) {
return makeTask(project, name, type);
}
/**
* Permit to create a Task instance of the type in a project
*
* @param target The target project
* @param name The name of the task
* @param type The type of the task that will be used to create an instance
* @return The created task object for the specified project
*/
public static <T extends Task> T makeTask(Project target, String name, Class<T> type) {
return target.getTasks().create(name, type);
}
/**
* Permit to add a Maven repository to a target project
*
* @param target The garget project
* @param name The name 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
*/
public MavenArtifactRepository addMavenRepo(Project target, final String name, final String url) {
return target.getRepositories().maven(repo -> {
repo.setName(name);
repo.setUrl(url);
});
}
/**
* Add Minecraft dependencies to IDE dependencies
*/
protected void configureIDEs() {
// IDEA
IdeaModel ideaModule = (IdeaModel) project.getExtensions().getByName("idea");
ideaModule.getModule().getExcludeDirs().addAll(project.files(".gradle", "build", ".idea", "out").getFiles());
ideaModule.getModule().setDownloadJavadoc(true);
ideaModule.getModule().setDownloadSources(true);
ideaModule.getModule().setInheritOutputDirs(true);
ideaModule.getModule().getScopes().get("COMPILE").get("plus").add(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES));
// ECLIPSE
EclipseModel eclipseModule = (EclipseModel) project.getExtensions().getByName("eclipse");
eclipseModule.getClasspath().getPlusConfigurations().add(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES));
}
/**
* Add Minecraft dependencies to compile time
*/
protected void configureCompile() {
JavaPluginConvention javaModule = (JavaPluginConvention) project.getConvention().getPlugins().get("java");
SourceSet main = javaModule.getSourceSets().getByName(SourceSet.MAIN_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)));
test.setCompileClasspath(test.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)));
Javadoc javadoc = (Javadoc) project.getTasks().getByName(JavaPlugin.JAVADOC_TASK_NAME);
javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath()));
}
}

View File

@ -0,0 +1,6 @@
package chorusmc.gradle;
public class ChorusGradleExtension {
public String version;
public String runDir = "run";
}

View File

@ -0,0 +1,19 @@
package chorusmc.gradle;
import chorusmc.gradle.task.*;
import org.gradle.api.DefaultTask;
import org.gradle.api.Project;
public class ChorusGradlePlugin extends AbstractPlugin {
@Override
public void apply(Project target) {
super.apply(target);
makeTask("download", DownloadTask.class);
makeTask("mapJars", MapJarsTask.class).dependsOn("download");
makeTask("setupChorus", DefaultTask.class).dependsOn("mapJars");
makeTask("extractNatives", ExtractNativesTask.class).dependsOn("download");
makeTask("genIdeaRuns", GenIdeaProjectTask.class).dependsOn("cleanIdea").dependsOn("idea").dependsOn("extractNatives");
}
}

View File

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

View File

@ -0,0 +1,124 @@
package chorusmc.gradle.task;
import chorusmc.gradle.util.Constants;
import chorusmc.gradle.util.Version;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.commons.io.FileUtils;
import org.gradle.api.DefaultTask;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.dsl.DependencyHandler;
import org.gradle.api.tasks.TaskAction;
import chorusmc.gradle.ChorusGradleExtension;
import chorusmc.gradle.util.Checksum;
import chorusmc.gradle.util.ManifestVersion;
import chorusmc.gradle.util.assets.AssetIndex;
import chorusmc.gradle.util.assets.AssetObject;
import chorusmc.gradle.util.progress.ProgressLogger;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.Optional;
public class DownloadTask extends DefaultTask {
@TaskAction
public void download() {
try {
ChorusGradleExtension extension = this.getProject().getExtensions().getByType(ChorusGradleExtension.class);
if (!Constants.MINECRAFT_JSON.get(extension).exists()) {
this.getLogger().lifecycle(":downloading minecraft json");
FileUtils.copyURLToFile(new URL("https://launchermeta.mojang.com/mc/game/version_manifest.json"), Constants.VERSION_MANIFEST);
ManifestVersion mcManifest = new GsonBuilder().create().fromJson(FileUtils.readFileToString(Constants.VERSION_MANIFEST), ManifestVersion.class);
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 {
this.getLogger().info(":failed downloading minecraft json");
throw new RuntimeException("Failed downloading Minecraft json");
}
}
Gson gson = new Gson();
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)) {
this.getLogger().lifecycle(":downloading client");
FileUtils.copyURLToFile(new URL(version.downloads.get("client").url), Constants.MINECRAFT_CLIENT_JAR.get(extension));
}
if (Constants.MAPPINGS_ZIP.exists()) {
Constants.MAPPINGS_ZIP.delete();
}
this.getLogger().lifecycle(":downloading mappings");
FileUtils.copyURLToFile(new URL("https://github.com/ChorusMC/pomf/archive/master.zip"), Constants.MAPPINGS_ZIP);
DependencyHandler dependencyHandler = getProject().getDependencies();
if (getProject().getConfigurations().getByName(Constants.CONFIG_MC_DEPENDENCIES).getState() == Configuration.State.UNRESOLVED) {
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) {
version.libraries.stream().filter(lib -> lib.natives != null).forEach(lib -> dependencyHandler.add(Constants.CONFIG_NATIVES, lib.getArtifactName()));
}
// Force add LaunchWrapper
dependencyHandler.add(Constants.CONFIG_MC_DEPENDENCIES, "net.minecraft:launchwrapper:1.11");
Version.AssetIndex assetIndex = version.assetIndex;
File assets = new File(Constants.CACHE_FILES, "assets");
if (!assets.exists()) {
assets.mkdirs();
}
File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.id + ".json");
if (!assetsInfo.exists() || !Checksum.equals(assetsInfo, assetIndex.sha1)) {
this.getLogger().lifecycle(":downloading asset index");
FileUtils.copyURLToFile(new URL(assetIndex.url), assetsInfo);
}
ProgressLogger progressLogger = ProgressLogger.getProgressFactory(getProject(), getClass().getName());
progressLogger.start("Downloading assets...", "assets");
AssetIndex index = new Gson().fromJson(new FileReader(assetsInfo), AssetIndex.class);
Map<String, AssetObject> parent = index.getFileMap();
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();
}
}
}

View File

@ -0,0 +1,20 @@
package chorusmc.gradle.task;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;
import org.zeroturnaround.zip.ZipUtil;
import chorusmc.gradle.util.Constants;
import java.io.File;
import java.io.FileNotFoundException;
public class ExtractNativesTask extends DefaultTask {
@TaskAction
public void extractNatives() throws FileNotFoundException {
if (!Constants.MINECRAFT_NATIVES.exists()) {
for (File source : getProject().getConfigurations().getByName(Constants.CONFIG_NATIVES)) {
ZipUtil.unpack(source, Constants.MINECRAFT_NATIVES);
}
}
}
}

View File

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

View File

@ -0,0 +1,68 @@
package chorusmc.gradle.task;
import cuchaz.enigma.Deobfuscator;
import cuchaz.enigma.mapping.MappingsEnigmaReader;
import cuchaz.enigma.throwables.MappingParseException;
import groovy.lang.Closure;
import org.apache.commons.io.FileUtils;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;
import org.gradle.process.ExecResult;
import org.gradle.process.JavaExecSpec;
import chorusmc.gradle.ChorusGradleExtension;
import chorusmc.gradle.util.Constants;
import org.zeroturnaround.zip.ZipUtil;
import java.io.File;
import java.io.IOException;
import java.util.jar.JarFile;
public class MapJarsTask extends DefaultTask {
Deobfuscator deobfuscator;
@TaskAction
public void mapJars() throws IOException, MappingParseException {
ChorusGradleExtension extension = this.getProject().getExtensions().getByType(ChorusGradleExtension.class);
if(Constants.MINECRAFT_CLIENT_MAPPED_JAR.get(extension).exists()){
Constants.MINECRAFT_CLIENT_MAPPED_JAR.get(extension).delete();
}
this.getLogger().lifecycle(":unpacking mappings");
if(Constants.MAPPINGS_DIR.exists()){
FileUtils.deleteDirectory(Constants.MAPPINGS_DIR);
}
ZipUtil.unpack(Constants.MAPPINGS_ZIP, Constants.MAPPINGS_DIR);
this.getLogger().lifecycle(":remapping jar");
deobfuscator = new Deobfuscator(new JarFile(Constants.MINECRAFT_CLIENT_JAR.get(extension)));
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());
File tempAssests = new File(Constants.CACHE_FILES, "tempAssets");
ZipUtil.unpack(Constants.MINECRAFT_CLIENT_JAR.get(extension), tempAssests, name -> {
if (name.startsWith("assets") || name.startsWith("log4j2.xml")) {
return name;
} else {
return null;
}
});
ZipUtil.unpack(Constants.MINECRAFT_CLIENT_MAPPED_JAR.get(extension), tempAssests);
ZipUtil.pack(tempAssests, Constants.MINECRAFT_CLIENT_MAPPED_JAR.get(extension));
}
public static class ProgressListener implements Deobfuscator.ProgressListener {
@Override
public void init(int i, String s) {
}
@Override
public void onProgress(int i, String s) {
}
}
}

View File

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

View File

@ -0,0 +1,49 @@
package chorusmc.gradle.util;
import chorusmc.gradle.util.delayed.IDelayed;
import chorusmc.gradle.util.delayed.DelayedFile;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
public class Constants {
public static final File WORKING_DIRECTORY = new File(".");
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_MAPPED_JAR = new DelayedFile(extension -> new File(CACHE_FILES, extension.version + "-client-mapped.jar"));
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 MINECRAFT_LIBS = new File(CACHE_FILES, "libs");
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 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 File VERSION_MANIFEST = new File(CACHE_FILES, "version_manifest.json");
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 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_MC_DEPENDENCIES = "MC_DEPENDENCIES";
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 List<String> getClassPath() {
URL[] urls = ((URLClassLoader) Constants.class.getClassLoader()).getURLs();
ArrayList<String> list = new ArrayList<>();
for (URL url : urls) {
list.add(url.getPath());
}
return list;
}
}

View File

@ -0,0 +1,48 @@
package chorusmc.gradle.util;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.io.IOException;
import java.util.Map;
public class IdeaRunConfig {
public String configName;
public String projectName;
public String mainClass;
public String runDir;
public String arguments;
public Element genRuns(Element doc) throws IOException, ParserConfigurationException, TransformerException {
Element root = this.addXml(doc, "component", ImmutableMap.of("name", "ProjectRunConfigurationManager"));
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, "option", ImmutableMap.of("name", "MAIN_CLASS_NAME", "value", mainClass));
this.addXml(root, "option", ImmutableMap.of("name", "WORKING_DIRECTORY", "value", runDir));
if (!Strings.isNullOrEmpty(arguments)) {
this.addXml(root, "option", ImmutableMap.of("name", "PROGRAM_PARAMETERS", "value", arguments));
}
return root;
}
public Element addXml(Node parent, String name, Map<String, String> values) {
Document doc = parent.getOwnerDocument();
if (doc == null) {
doc = (Document) parent;
}
Element e = doc.createElement(name);
for (Map.Entry<String, String> entry : values.entrySet()) {
e.setAttribute(entry.getKey(), entry.getValue());
}
parent.appendChild(e);
return e;
}
}

View File

@ -0,0 +1,12 @@
package chorusmc.gradle.util;
import java.util.ArrayList;
import java.util.List;
public class ManifestVersion {
public List<Versions> versions = new ArrayList<>();
public static class Versions {
public String id, url;
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,23 @@
package chorusmc.gradle.util.delayed;
import chorusmc.gradle.ChorusGradleExtension;
import java.io.File;
import java.util.function.Function;
public class DelayedFile implements IDelayed<File> {
private File file;
private Function<ChorusGradleExtension, File> function;
public DelayedFile(Function<ChorusGradleExtension, File> function) {
this.function = function;
}
@Override
public File get(ChorusGradleExtension extension) {
if (this.file == null) {
this.file = this.function.apply(extension);
}
return this.file;
}
}

View File

@ -0,0 +1,7 @@
package chorusmc.gradle.util.delayed;
import chorusmc.gradle.ChorusGradleExtension;
public interface IDelayed<T> {
T get(ChorusGradleExtension extension);
}

View File

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

View File

@ -0,0 +1 @@
implementation-class=chorusmc.gradle.ChorusGradlePlugin