/*
* A Gradle plugin for the creation of Minecraft mods and MinecraftForge plugins.
* Copyright (C) 2013 Minecraft Forge
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*/
package net.minecraftforge.gradle.user.patcherUser;
import static net.minecraftforge.gradle.common.Constants.DIR_JSONS;
import static net.minecraftforge.gradle.common.Constants.JAR_MERGED;
import static net.minecraftforge.gradle.common.Constants.MCP_PATCHES_MERGED;
import static net.minecraftforge.gradle.common.Constants.TASK_DL_VERSION_JSON;
import static net.minecraftforge.gradle.common.Constants.TASK_GENERATE_SRGS;
import static net.minecraftforge.gradle.common.Constants.TASK_MERGE_JARS;
import static net.minecraftforge.gradle.common.Constants.DIR_LOCAL_CACHE;
import static net.minecraftforge.gradle.user.UserConstants.*;
import static net.minecraftforge.gradle.user.patcherUser.PatcherUserConstants.*;
import java.io.File;
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import com.google.common.collect.ImmutableMap;
import groovy.lang.Closure;
import net.minecraftforge.gradle.tasks.DeobfuscateJar;
import net.minecraftforge.gradle.tasks.ExtractConfigTask;
import net.minecraftforge.gradle.tasks.PatchSourcesTask;
import net.minecraftforge.gradle.tasks.RemapSources;
import net.minecraftforge.gradle.user.TaskSingleReobf;
import net.minecraftforge.gradle.user.UserBaseExtension;
import net.minecraftforge.gradle.user.UserBasePlugin;
public abstract class PatcherUserBasePlugin<T extends UserBaseExtension> extends UserBasePlugin<T>
{
@Override
@SuppressWarnings("serial")
protected void applyUserPlugin()
{
// add the MC setup tasks..
String global = DIR_API_JAR_BASE + "/" + REPLACE_API_NAME + "%s-" + REPLACE_API_VERSION;
String local = DIR_LOCAL_CACHE + "/" + REPLACE_API_NAME + "%s-" + REPLACE_API_VERSION + "-PROJECT(" + project.getName() + ")";
// grab ATs from resource dirs
JavaPluginConvention javaConv = (JavaPluginConvention) project.getConvention().getPlugins().get("java");
SourceSet main = javaConv.getSourceSets().getByName("main");
SourceSet api = javaConv.getSourceSets().getByName("api");
getExtension().atSources(main, api);
this.makeDecompTasks(global, local, delayedFile(JAR_MERGED), TASK_MERGE_JARS, delayedFile(MCP_PATCHES_MERGED));
// setup userdev
{
project.getConfigurations().maybeCreate(CONFIG_USERDEV);
ExtractConfigTask extractUserdev = makeTask(TASK_EXTRACT_USERDEV, ExtractConfigTask.class);
extractUserdev.setDestinationDir(delayedFile(DIR_USERDEV));
extractUserdev.setConfig(CONFIG_USERDEV);
extractUserdev.exclude("META-INF/**", "META-INF/**");
extractUserdev.dependsOn(TASK_DL_VERSION_JSON);
extractUserdev.doLast(new Closure<Boolean>(project) // normalizes to linux endings
{
@Override
public Boolean call()
{
parseAndStoreVersion(delayedFile(JSON_USERDEV).call(), delayedFile(DIR_JSONS).call());
return true;
}
});
// See afterEvaluate for more config
project.getTasks().getByName(TASK_GENERATE_SRGS).dependsOn(extractUserdev);
project.getTasks().getByName(TASK_RECOMPILE).dependsOn(extractUserdev);
project.getTasks().getByName(TASK_MAKE_START).dependsOn(extractUserdev);
}
// setup deobfuscation
{
DeobfuscateJar deobfBin = (DeobfuscateJar) project.getTasks().getByName(TASK_DEOBF_BIN);
DeobfuscateJar deobf = (DeobfuscateJar) project.getTasks().getByName(TASK_DEOBF);
deobfBin.addAt(delayedFile(AT_USERDEV));
deobf.addAt(delayedFile(AT_USERDEV));
}
// setup binpatching
{
final Object patchedJar = chooseDeobfOutput(global, local, "", "binpatched");
TaskApplyBinPatches task = makeTask(TASK_BINPATCH, TaskApplyBinPatches.class);
task.setInJar(delayedFile(JAR_MERGED));
task.setOutJar(patchedJar);
task.setPatches(delayedFile(BINPATCH_USERDEV));
task.setClassJar(delayedFile(ZIP_UD_CLASSES));
task.setResourceJar(delayedFile(ZIP_UD_RES));
task.dependsOn(TASK_MERGE_JARS, TASK_EXTRACT_USERDEV);
project.getTasks().getByName(TASK_DEOBF_BIN).dependsOn(task);
DeobfuscateJar deobf = (DeobfuscateJar) project.getTasks().getByName(TASK_DEOBF_BIN).dependsOn(task);
deobf.setInJar(patchedJar);
deobf.dependsOn(task);
}
// setup source patching
{
final Object postDecompJar = chooseDeobfOutput(global, local, "", "decompFixed");
final Object patchedJar = chooseDeobfOutput(global, local, "", "patched");
PatchSourcesTask patch = makeTask(TASK_PATCH, PatchSourcesTask.class);
patch.setPatches(delayedFile(ZIP_UD_PATCHES));
patch.addInject(delayedFile(ZIP_UD_SRC));
patch.addInject(delayedFile(ZIP_UD_RES)); // injecting teh resources too... the src jar needs them afterall.
patch.setFailOnError(true);
patch.setMakeRejects(false);
patch.setPatchStrip(1);
patch.setInJar(postDecompJar);
patch.setOutJar(patchedJar);
patch.dependsOn(TASK_POST_DECOMP);
RemapSources remap = (RemapSources) project.getTasks().getByName(TASK_REMAP);
remap.setInJar(patchedJar);
remap.dependsOn(patch);
}
// setup reobf
{
TaskSingleReobf reobf = (TaskSingleReobf) project.getTasks().getByName(TASK_REOBF);
reobf.addSecondarySrgFile(delayedFile(SRG_USERDEV));
// still need to set the primary SRG
}
}
@Override
protected void afterEvaluate()
{
// add replacements
T ext = getExtension();
replacer.putReplacement(REPLACE_API_GROUP, getApiGroup(ext));
replacer.putReplacement(REPLACE_API_GROUP_DIR, getApiGroup(ext).replace('.', '/'));
replacer.putReplacement(REPLACE_API_NAME, getApiName(ext));
replacer.putReplacement(REPLACE_API_VERSION, getApiVersion(ext));
// read version file if exists
{
File jsonFile = delayedFile(JSON_USERDEV).call();
if (jsonFile.exists())
{
parseAndStoreVersion(jsonFile, delayedFile(DIR_JSONS).call());
}
}
super.afterEvaluate();
// add userdev dep
project.getDependencies().add(CONFIG_USERDEV, ImmutableMap.of(
"group", getApiGroup(ext),
"name", getApiName(ext),
"version", getApiVersion(ext),
"classifier", getUserdevClassifier(ext),
"ext", getUserdevExtension(ext)
));
}
@Override
protected void afterDecomp(final boolean isDecomp, final boolean useLocalCache, final String mcConfig)
{
// add MC repo to all projects
project.allprojects(new Action<Project>() {
@Override
public void execute(Project proj)
{
addFlatRepo(proj, "TweakerMcRepo", delayedFile(useLocalCache ? DIR_LOCAL_CACHE : DIR_API_JAR_BASE).call());
}
});
// add the Mc dep
T exten = getExtension();
String group = getApiGroup(exten);
String artifact = getApiName(exten) + (isDecomp ? "Src" : "Bin");
String version = getApiVersion(exten) + (useLocalCache ? "-PROJECT(" + project.getName() + ")" : "");
project.getDependencies().add(CONFIG_MC, ImmutableMap.of("group", group, "name", artifact, "version", version));
}
@Override
protected Object getStartDir()
{
return delayedFile(DIR_API_BASE + "/start");
}
public abstract String getApiGroup(T ext);
public abstract String getApiName(T ext);
public abstract String getApiVersion(T ext);
public abstract String getUserdevClassifier(T ext);
public abstract String getUserdevExtension(T ext);
//@formatter:off
@Override protected boolean hasServerRun() { return true; }
@Override protected boolean hasClientRun() { return true; }
//@formatter:on
}