Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.minecraftforge.gradle.patcher.PatcherPlugin Maven / Gradle / Ivy
/*
* A Gradle plugin for the creation of Minecraft mods and MinecraftForge plugins.
* Copyright (C) 2013-2019 Minecraft Forge
* Copyright (C) 2020-2021 anatawa12 and other contributors
*
* 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.patcher;
import static net.minecraftforge.gradle.common.Constants.*;
import static net.minecraftforge.gradle.patcher.PatcherConstants.*;
import groovy.lang.Closure;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import net.minecraftforge.gradle.ArchiveTaskHelper;
import net.minecraftforge.gradle.common.BasePlugin;
import net.minecraftforge.gradle.common.Constants;
import net.minecraftforge.gradle.tasks.*;
import net.minecraftforge.gradle.tasks.fernflower.ApplyFernFlowerTask;
import net.minecraftforge.gradle.util.CopyInto;
import net.minecraftforge.gradle.util.GradleConfigurationException;
import net.minecraftforge.gradle.util.json.version.Library;
import net.minecraftforge.gradle.util.json.version.Version;
import org.gradle.api.Action;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Task;
import org.gradle.api.file.DuplicatesStrategy;
import org.gradle.api.tasks.Delete;
import org.gradle.api.tasks.bundling.Jar;
import org.gradle.api.tasks.bundling.Zip;
import com.google.common.base.Strings;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.io.Resources;
public class PatcherPlugin extends BasePlugin
{
@Override
public void applyPlugin()
{
// create and add the namedDomainObjectContainer to the extension object
NamedDomainObjectContainer container = project.container(PatcherProject.class, new PatcherProjectFactory(this));
getExtension().setProjectContainer(container);
container.whenObjectAdded(new Action() {
@Override
public void execute(PatcherProject arg0)
{
createProject(arg0);
}
});
container.whenObjectRemoved(new Action() {
@Override
public void execute(PatcherProject arg0)
{
removeProject(arg0);
}
});
// top level tasks
{
Task task = makeTask(TASK_SETUP);
task.setGroup(GROUP_FG);
task.setDescription("Sets up all the projects complete with run configurations for both Eclipse and Intellij");
Delete cleanTask = maybeMakeTask(TASK_CLEAN, Delete.class);
cleanTask.delete(getExtension().getDelayedWorkspaceDir());
cleanTask.delete(project.getBuildDir());
cleanTask.setGroup(GROUP_FG);
cleanTask.setDescription("Completely cleans the workspace for a fresh build. Deletes the 'build' folder and the specified workspaceDir");
task = makeTask(TASK_GEN_PATCHES);
task.setGroup(GROUP_FG);
task.setDescription("Generates patches for all the configured projects. (requires that setup was run before hand)");
task = maybeMakeTask(TASK_BUILD);
task.setGroup(GROUP_FG);
task.setDescription("Builds all output packages. (outputs found in build/distributions)");
}
makeGeneralSetupTasks();
makePackagingTasks();
makeCleanTasks();
}
protected void makeGeneralSetupTasks()
{
DeobfuscateJar deobfJar = makeTask(TASK_DEOBF, DeobfuscateJar.class);
{
deobfJar.setInJar(delayedFile(Constants.JAR_MERGED));
deobfJar.setOutJar(delayedFile(JAR_DEOBF));
deobfJar.setSrg(delayedFile(SRG_NOTCH_TO_SRG));
deobfJar.setExceptorCfg(delayedFile(EXC_SRG));
deobfJar.setExceptorJson(delayedFile(MCP_DATA_EXC_JSON));
deobfJar.setApplyMarkers(true);
deobfJar.setDoesCache(false);
// access transformers are added afterEvaluate
deobfJar.dependsOn(TASK_MERGE_JARS, TASK_GENERATE_SRGS);
}
ApplyFernFlowerTask decompileJar = makeTask(TASK_DECOMP, ApplyFernFlowerTask.class);
{
decompileJar.setInJar(delayedFile(JAR_DEOBF));
decompileJar.setOutJar(delayedFile(JAR_DECOMP));
decompileJar.setDoesCache(false);
decompileJar.setClasspath(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPS));
decompileJar.setForkedClasspath(project.getConfigurations().getByName(Constants.CONFIG_FFI_DEPS));
decompileJar.dependsOn(deobfJar);
}
PostDecompileTask postDecompileJar = makeTask(TASK_POST_DECOMP, PostDecompileTask.class);
{
postDecompileJar.setInJar(delayedFile(JAR_DECOMP));
postDecompileJar.setOutJar(delayedFile(JAR_DECOMP_POST));
postDecompileJar.setPatches(delayedFile(MCP_PATCHES_MERGED));
postDecompileJar.setInjects(delayedFile(MCP_INJECT));
postDecompileJar.setAstyleConfig(delayedFile(MCP_DATA_STYLE));
postDecompileJar.setDoesCache(false);
postDecompileJar.dependsOn(decompileJar);
}
TaskGenSubprojects createProjects = makeTask(TASK_GEN_PROJECTS, TaskGenSubprojects.class);
{
createProjects.setWorkspaceDir(getExtension().getDelayedWorkspaceDir());
createProjects.addRepo("minecraft", Constants.URL_LIBRARY);
createProjects.putProject("Clean", null, null, null, null);
createProjects.setJavaLevel("1.8");
}
Task setupProjects = makeTask(TASK_SETUP_PROJECTS);
setupProjects.dependsOn(createProjects);
TaskSubprojectCall makeIdeProjects = makeTask(TASK_GEN_IDES, TaskSubprojectCall.class);
{
makeIdeProjects.setProjectDir(getExtension().getDelayedWorkspaceDir());
makeIdeProjects.setCallLine("cleanEclipse cleanIdea eclipse idea");
makeIdeProjects.dependsOn(setupProjects);
}
}
protected void makePackagingTasks()
{
// for universal
TaskReobfuscate obf = makeTask(TASK_REOBFUSCATE, TaskReobfuscate.class);
{
obf.setSrg(delayedFile(SRG_MCP_TO_NOTCH));
obf.setExc(delayedFile(EXC_MCP));
obf.setPreFFJar(delayedFile(JAR_DEOBF));
obf.setMethodsCsv(delayedFile(CSV_METHOD));
obf.setFieldsCsv(delayedFile(CSV_FIELD));
obf.setOutJar(delayedFile(JAR_OBFUSCATED));
obf.addLibs(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPS));
obf.dependsOn(TASK_GENERATE_SRGS, TASK_SETUP_PROJECTS);
}
TaskGenBinPatches genBinPatches = makeTask(TASK_GEN_BIN_PATCHES, TaskGenBinPatches.class);
{
genBinPatches.setCleanClient(delayedFile(JAR_CLIENT_FRESH));
genBinPatches.setCleanServer(delayedFile(JAR_SERVER_FRESH));
genBinPatches.setCleanMerged(delayedFile(JAR_MERGED));
genBinPatches.setDirtyJar(delayedFile(JAR_OBFUSCATED));
genBinPatches.setSrg(delayedFile(SRG_NOTCH_TO_SRG));
genBinPatches.setRuntimeBinPatches(delayedFile(BINPATCH_RUN));
genBinPatches.setDevBinPatches(delayedFile(BINPATCH_DEV));
genBinPatches.dependsOn(obf);
}
TaskExtractNew extractObfClasses = makeTask(TASK_EXTRACT_OBF_CLASSES, TaskExtractNew.class);
{
// why not merged? it contains the SideOnly and stuff that we want in the classes
extractObfClasses.addCleanSource(delayedFile(JAR_CLIENT_FRESH));
extractObfClasses.addCleanSource(delayedFile(JAR_SERVER_FRESH));
extractObfClasses.addDirtySource(delayedFile(JAR_OBFUSCATED));
extractObfClasses.setOutput(delayedFile(JAR_OBF_CLASSES));
extractObfClasses.setEnding(".class");
extractObfClasses.dependsOn(obf);
}
TaskCompressLZMA compressDeobf = makeTask("compressDeobf", TaskCompressLZMA.class);
{
compressDeobf.setInputFile(delayedFile(MCP_DATA_SRG)); // SRG_NOTCH_TO_SRG but doesnt require genSrgs task
compressDeobf.setOutputFile(delayedFile(DEOBF_DATA));
compressDeobf.dependsOn(TASK_EXTRACT_MCP);
}
TaskProcessJson procJson = makeTask(TASK_PROCESS_JSON, TaskProcessJson.class);
{
procJson.setInstallerJson(delayedFile(JSON_INSTALLER));
procJson.setUniversalJson(delayedFile(JSON_UNIVERSAL));
procJson.getOutputs().upToDateWhen(Constants.CALL_FALSE);
}
Jar outputJar = makeTask(TASK_OUTPUT_JAR, Jar.class);
{
outputJar.from(delayedTree(JAR_OBF_CLASSES));
outputJar.from(delayedFile(BINPATCH_RUN));
outputJar.from(delayedFile(DEOBF_DATA));
outputJar.from(delayedFile(JSON_UNIVERSAL));
ArchiveTaskHelper.setBaseName(outputJar, project.getName());
outputJar.setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE);
outputJar.getOutputs().upToDateWhen(Constants.CALL_FALSE); // rebuild every time.
ArchiveTaskHelper.setDestinationDir(outputJar, new File(DIR_OUTPUT));
outputJar.dependsOn(genBinPatches, extractObfClasses, compressDeobf, procJson);
}
// add to build
project.getTasks().getByName(TASK_BUILD).dependsOn(outputJar);
// ------------------------------
// for installer
EtagDownloadTask dlInstaller = makeTask("downloadInstaller", EtagDownloadTask.class);
{
dlInstaller.setUrl(delayedString(INSTALLER_URL));
dlInstaller.setDieWithError(true);
dlInstaller.setFile(delayedFile(JAR_INSTALLER));
}
Zip installer = makeTask(TASK_BUILD_INSTALLER, Zip.class);
{
installer.from(outputJar);
installer.from(delayedTree(JAR_INSTALLER), new CopyInto(PatcherPlugin.class, "", "!*.json", "!*.png"));
installer.from(delayedTree(JSON_INSTALLER));
ArchiveTaskHelper.setBaseName(installer, project.getName());
ArchiveTaskHelper.setClassifier(installer, "installer");
ArchiveTaskHelper.setExtension(installer, "jar");
ArchiveTaskHelper.setDestinationDir(installer, new File(DIR_OUTPUT));
installer.setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE);
installer.getOutputs().upToDateWhen(Constants.CALL_FALSE); // rebuild every time.
installer.dependsOn(dlInstaller, outputJar, procJson);
}
// ------------------------------
// for userdev
TaskExtractNew extractNonMcSources = makeTask(TASK_EXTRACT_OBF_SOURCES, TaskExtractNew.class);
{
// why not merged? it contains the SideOnly and stuff that we want in the classes
extractNonMcSources.addCleanSource(delayedFile(JAR_DECOMP_POST));
extractNonMcSources.setOutput(delayedFile(ZIP_USERDEV_SOURCES));
extractNonMcSources.setEnding(".java");
extractNonMcSources.dependsOn(TASK_SETUP_PROJECTS);
}
Zip combineRes = makeTask(TASK_COMBINE_RESOURCES, Zip.class);
{
File out = delayedFile(ZIP_USERDEV_RES).call();
ArchiveTaskHelper.setDestinationDir(combineRes, out.getParentFile());
ArchiveTaskHelper.setArchiveName(combineRes, out.getName());
combineRes.setIncludeEmptyDirs(false);
combineRes.setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE);
}
TaskMergeFiles mergeFiles = makeTask(TASK_MERGE_FILES, TaskMergeFiles.class);
{
mergeFiles.setOutSrg(delayedFile(SRG_MERGED_USERDEV));
mergeFiles.setOutExc(delayedFile(EXC_MERGED_USERDEV));
mergeFiles.setOutAt(delayedFile(AT_MERGED_USERDEV));
}
TaskGenPatches userdevPatches = makeTask(TASK_GEN_PATCHES_USERDEV, TaskGenPatches.class);
{
userdevPatches.setPatchDir(delayedFile(DIR_USERDEV_PATCHES));
userdevPatches.addOriginalSource(delayedFile(JAR_DECOMP_POST)); // add vanilla SRG named source
}
Zip packagePatches = makeTask(TASK_PATCHES_USERDEV, Zip.class);
{
File out = delayedFile(ZIP_USERDEV_PATCHES).call();
ArchiveTaskHelper.setDestinationDir(packagePatches, out.getParentFile());
ArchiveTaskHelper.setArchiveName(packagePatches, out.getName());
packagePatches.from(delayedFile(DIR_USERDEV_PATCHES));
packagePatches.dependsOn(userdevPatches);
}
Zip userdev = makeTask(TASK_BUILD_USERDEV, Zip.class);
{
userdev.from(delayedFile(DIR_USERDEV));
userdev.from(getExtension().getDelayedVersionJson()); // cant forge that now can we..
userdev.rename(".+-dev\\.json", "dev.json");
ArchiveTaskHelper.setBaseName(userdev, project.getName());
ArchiveTaskHelper.setClassifier(userdev, "userdev");
ArchiveTaskHelper.setExtension(userdev, "jar");
ArchiveTaskHelper.setDestinationDir(userdev, new File(DIR_OUTPUT));
userdev.setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE);
userdev.getOutputs().upToDateWhen(Constants.CALL_FALSE); // rebuild every time.
userdev.dependsOn(genBinPatches, extractObfClasses, packagePatches, extractNonMcSources, combineRes, mergeFiles);
}
}
protected void makeCleanTasks()
{
RemapSources remapCleanTask = makeTask(TASK_CLEAN_REMAP, RemapSources.class);
{
remapCleanTask.setInJar(delayedFile(JAR_DECOMP_POST));
remapCleanTask.setOutJar(delayedFile(JAR_REMAPPED));
remapCleanTask.setMethodsCsv(delayedFile(Constants.CSV_METHOD));
remapCleanTask.setFieldsCsv(delayedFile(Constants.CSV_FIELD));
remapCleanTask.setParamsCsv(delayedFile(Constants.CSV_PARAM));
remapCleanTask.setAddsJavadocs(false);
remapCleanTask.setDoesCache(false);
remapCleanTask.dependsOn(TASK_POST_DECOMP);
}
Object delayedRemapped = delayedFile(JAR_REMAPPED);
ExtractTask extractSrc = makeTask(TASK_CLEAN_EXTRACT_SRC, ExtractTask.class);
{
extractSrc.from(delayedRemapped);
extractSrc.into(subWorkspace("Clean" + DIR_EXTRACTED_SRC));
extractSrc.include("*.java", "**/*.java");
extractSrc.setDoesCache(false);
extractSrc.dependsOn(remapCleanTask, TASK_GEN_PROJECTS);
}
ExtractTask extractRes = makeTask(TASK_CLEAN_EXTRACT_RES, ExtractTask.class);
{
extractRes.from(delayedRemapped);
extractRes.into(subWorkspace("Clean" + DIR_EXTRACTED_RES));
extractRes.exclude("*.java", "**/*.java");
extractRes.setDoesCache(false);
extractRes.dependsOn(remapCleanTask, TASK_GEN_PROJECTS);
}
CreateStartTask makeStart = makeTask(TASK_CLEAN_MAKE_START, CreateStartTask.class);
{
for (String resource : GRADLE_START_RESOURCES)
{
makeStart.addResource(resource);
}
makeStart.addReplacement("@@ASSETINDEX@@", delayedString(REPLACE_ASSET_INDEX));
makeStart.addReplacement("@@ASSETSDIR@@", delayedFile(DIR_ASSETS));
makeStart.addReplacement("@@NATIVESDIR@@", delayedFile(Constants.DIR_NATIVES));
makeStart.addReplacement("@@SRGDIR@@", delayedFile(DIR_MCP_MAPPINGS + "/srgs/"));
makeStart.addReplacement("@@SRG_NOTCH_SRG@@", delayedFile(SRG_NOTCH_TO_SRG));
makeStart.addReplacement("@@SRG_NOTCH_MCP@@", delayedFile(SRG_NOTCH_TO_MCP));
makeStart.addReplacement("@@SRG_SRG_MCP@@", delayedFile(SRG_SRG_TO_MCP));
makeStart.addReplacement("@@SRG_MCP_SRG@@", delayedFile(SRG_MCP_TO_SRG));
makeStart.addReplacement("@@SRG_MCP_NOTCH@@", delayedFile(SRG_MCP_TO_NOTCH));
makeStart.addReplacement("@@CSVDIR@@", delayedFile(DIR_MCP_MAPPINGS));
makeStart.addReplacement("@@BOUNCERCLIENT@@", "net.minecraft.client.main.Main");
makeStart.addReplacement("@@TWEAKERCLIENT@@", "");
makeStart.addReplacement("@@BOUNCERSERVER@@", "net.minecraft.server.MinecraftServer");
makeStart.addReplacement("@@TWEAKERSERVER@@", "");
makeStart.setStartOut(subWorkspace("Clean" + DIR_EXTRACTED_START));
makeStart.setDoesCache(false);
makeStart.dependsOn(TASK_DL_ASSET_INDEX, TASK_DL_ASSETS, TASK_EXTRACT_NATIVES);
makeStart.getOutputs().upToDateWhen(Constants.CALL_FALSE); //TODO: Abrar, Fix this...
}
GenEclipseRunTask eclipseClient = makeTask(TASK_CLEAN_RUNE_CLIENT, GenEclipseRunTask.class);
{
eclipseClient.setMainClass(GRADLE_START_CLIENT);
eclipseClient.setProjectName("Clean");
eclipseClient.setOutputFile(subWorkspace("Clean/Clean Client.launch"));
eclipseClient.setRunDir(subWorkspace("run"));
eclipseClient.dependsOn(makeStart, TASK_GEN_IDES);
}
GenEclipseRunTask eclipseServer = makeTask(TASK_CLEAN_RUNE_SERVER, GenEclipseRunTask.class);
{
eclipseServer.setMainClass(GRADLE_START_SERVER);
eclipseServer.setProjectName("Clean");
eclipseServer.setOutputFile(subWorkspace("Clean/Clean Server.launch"));
eclipseServer.setRunDir(subWorkspace("run"));
eclipseServer.dependsOn(makeStart, TASK_GEN_IDES);
}
TaskGenIdeaRun ideaClient = makeTask(TASK_CLEAN_RUNJ_CLIENT, TaskGenIdeaRun.class);
{
ideaClient.setMainClass(GRADLE_START_CLIENT);
ideaClient.setProjectName("Clean");
ideaClient.setConfigName("Clean Client");
ideaClient.setOutputFile(subWorkspace("/.idea/runConfigurations/Clean_Client.xml"));
ideaClient.setRunDir("file://$PROJECT_DIR$/run");
ideaClient.dependsOn(makeStart, TASK_GEN_IDES);
}
TaskGenIdeaRun ideaServer = makeTask(TASK_CLEAN_RUNJ_SERVER, TaskGenIdeaRun.class);
{
ideaServer.setMainClass(GRADLE_START_SERVER);
ideaServer.setProjectName("Clean");
ideaServer.setConfigName("Clean Server");
ideaServer.setOutputFile(subWorkspace("/.idea/runConfigurations/Clean_Server.xml"));
ideaServer.setRunDir("file://$PROJECT_DIR$/run");
ideaServer.dependsOn(makeStart, TASK_GEN_IDES);
}
// add depends
project.getTasks().getByName(TASK_GEN_IDES).dependsOn(extractSrc, extractRes, makeStart);
project.getTasks().getByName(TASK_SETUP).dependsOn(eclipseClient, eclipseServer, ideaClient, ideaServer);
}
protected void createProject(PatcherProject patcher)
{
PatchSourcesTask patch = makeTask(projectString(TASK_PROJECT_PATCH, patcher), PatchSourcesTask.class);
{
// inJar is set afterEvaluate depending on the patch order.
patch.setOutJar(delayedFile(projectString(JAR_PROJECT_PATCHED, patcher)));
patch.setPatches(patcher.getDelayedPatchDir());
patch.setDoesCache(false);
patch.setMaxFuzz(2);
patch.setFailOnError(false);
patch.setMakeRejects(true);
patch.dependsOn(TASK_POST_DECOMP);
}
RemapSources remapTask = makeTask(projectString(TASK_PROJECT_REMAP_JAR, patcher), RemapSources.class);
{
// inJar is set afterEvaluate depending on the patch order.
remapTask.setOutJar(delayedFile(projectString(JAR_PROJECT_REMAPPED, patcher)));
remapTask.setMethodsCsv(delayedFile(Constants.CSV_METHOD));
remapTask.setFieldsCsv(delayedFile(Constants.CSV_FIELD));
remapTask.setParamsCsv(delayedFile(Constants.CSV_PARAM));
remapTask.setAddsJavadocs(false);
remapTask.setDoesCache(false);
remapTask.dependsOn(TASK_POST_DECOMP, TASK_EXTRACT_MAPPINGS);
// depend on patch task in afterEval
}
((TaskGenSubprojects) project.getTasks().getByName(TASK_GEN_PROJECTS)).putProject(
patcher.getCapName(),
patcher.getDelayedSourcesDir(),
patcher.getDelayedResourcesDir(),
patcher.getDelayedTestSourcesDir(),
patcher.getDelayedTestResourcesDir()
);
ExtractTask extractSrc = makeTask(projectString(TASK_PROJECT_EXTRACT_SRC, patcher), ExtractTask.class);
{
// set from() thing in afterEval
extractSrc.into(subWorkspace(patcher.getCapName() + DIR_EXTRACTED_SRC));
extractSrc.include("*.java", "**/*.java");
extractSrc.setDoesCache(false);
extractSrc.dependsOn(patch, remapTask, TASK_GEN_PROJECTS);
// if depends on both remap and patch, itl happen after whichever is second.
}
ExtractTask extractRes = makeTask(projectString(TASK_PROJECT_EXTRACT_RES, patcher), ExtractTask.class);
{
// set from() thing in afterEval
extractRes.into(subWorkspace(patcher.getCapName() + DIR_EXTRACTED_RES));
extractRes.exclude("*.java", "**/*.java");
extractRes.setDoesCache(false);
extractRes.dependsOn(patch, remapTask, TASK_GEN_PROJECTS);
// if depends on both remap and patch, itl happen after whichever is second.
}
Task setupTask = makeTask(projectString(TASK_PROJECT_SETUP, patcher));
setupTask.dependsOn(extractSrc, extractRes);
// Run config generation, not necessary unless its actual dev
CreateStartTask makeStart = makeTask(projectString(TASK_PROJECT_MAKE_START, patcher), CreateStartTask.class);
{
for (String resource : GRADLE_START_RESOURCES)
{
makeStart.addResource(resource);
}
for (String resource : GRADLE_START_FML_RES)
{
makeStart.addResource(resource);
}
makeStart.addReplacement("@@ASSETINDEX@@", delayedString(REPLACE_ASSET_INDEX));
makeStart.addReplacement("@@ASSETSDIR@@", delayedFile(DIR_ASSETS));
makeStart.addReplacement("@@NATIVESDIR@@", delayedFile(Constants.DIR_NATIVES));
makeStart.addReplacement("@@SRGDIR@@", delayedFile(DIR_MCP_MAPPINGS + "/srgs/"));
makeStart.addReplacement("@@SRG_NOTCH_SRG@@", delayedFile(SRG_NOTCH_TO_SRG));
makeStart.addReplacement("@@SRG_NOTCH_MCP@@", delayedFile(SRG_NOTCH_TO_MCP));
makeStart.addReplacement("@@SRG_SRG_MCP@@", delayedFile(SRG_SRG_TO_MCP));
makeStart.addReplacement("@@SRG_MCP_SRG@@", delayedFile(SRG_MCP_TO_SRG));
makeStart.addReplacement("@@SRG_MCP_NOTCH@@", delayedFile(SRG_MCP_TO_NOTCH));
makeStart.addReplacement("@@CSVDIR@@", delayedFile(DIR_MCP_MAPPINGS));
makeStart.addReplacement("@@BOUNCERCLIENT@@", patcher.getDelayedMainClassClient());
makeStart.addReplacement("@@TWEAKERCLIENT@@", patcher.getDelayedTweakClassClient());
makeStart.addReplacement("@@BOUNCERSERVER@@", patcher.getDelayedMainClassServer());
makeStart.addReplacement("@@TWEAKERSERVER@@", patcher.getDelayedTweakClassServer());
makeStart.addExtraLine("net.minecraftforge.gradle.GradleForgeHacks.searchCoremods(this);");
makeStart.setStartOut(subWorkspace(patcher.getCapName() + DIR_EXTRACTED_START));
makeStart.setDoesCache(false);
makeStart.dependsOn(TASK_DL_ASSET_INDEX, TASK_DL_ASSETS);
makeStart.getOutputs().upToDateWhen(Constants.CALL_FALSE); //TODO: Abrar, Fix this...
}
GenEclipseRunTask eclipseRunClient = makeTask(projectString(TASK_PROJECT_RUNE_CLIENT, patcher), GenEclipseRunTask.class);
{
eclipseRunClient.setMainClass(GRADLE_START_CLIENT);
eclipseRunClient.setArguments(patcher.getDelayedRunArgsClient());
eclipseRunClient.setProjectName(patcher.getCapName());
eclipseRunClient.setOutputFile(subWorkspace(patcher.getCapName() + "/" + patcher.getCapName() + " Client.launch"));
eclipseRunClient.setRunDir(subWorkspace("run"));
eclipseRunClient.dependsOn(makeStart, TASK_GEN_IDES);
}
GenEclipseRunTask eclipseRunServer = makeTask(projectString(TASK_PROJECT_RUNE_SERVER, patcher), GenEclipseRunTask.class);
{
eclipseRunServer.setMainClass(GRADLE_START_SERVER);
eclipseRunServer.setArguments(patcher.getDelayedRunArgsServer());
eclipseRunServer.setProjectName(patcher.getCapName());
eclipseRunServer.setOutputFile(subWorkspace(patcher.getCapName() + "/" + patcher.getCapName() + " Server.launch"));
eclipseRunServer.setRunDir(subWorkspace("run"));
eclipseRunServer.dependsOn(makeStart, TASK_GEN_IDES);
}
TaskGenIdeaRun ideaRunClient = makeTask(projectString(TASK_PROJECT_RUNJ_CLIENT, patcher), TaskGenIdeaRun.class);
{
ideaRunClient.setMainClass(GRADLE_START_CLIENT);
ideaRunClient.setArguments(patcher.getDelayedRunArgsClient());
ideaRunClient.setProjectName(patcher.getCapName());
ideaRunClient.setConfigName(patcher.getCapName() + " Client");
ideaRunClient.setOutputFile(subWorkspace("/.idea/runConfigurations/" + patcher.getCapName() + "Client.xml"));
ideaRunClient.setRunDir("file://$PROJECT_DIR$/run");
ideaRunClient.dependsOn(makeStart, TASK_GEN_IDES);
}
TaskGenIdeaRun ideaRunServer = makeTask(projectString(TASK_PROJECT_RUNJ_SERVER, patcher), TaskGenIdeaRun.class);
{
ideaRunServer.setMainClass(GRADLE_START_SERVER);
ideaRunServer.setArguments(patcher.getDelayedRunArgsServer());
ideaRunServer.setProjectName(patcher.getCapName());
ideaRunServer.setConfigName(patcher.getCapName() + " Server");
ideaRunServer.setOutputFile(subWorkspace("/.idea/runConfigurations/" + patcher.getCapName() + "Server.xml"));
ideaRunServer.setRunDir("file://$PROJECT_DIR$/run");
ideaRunServer.dependsOn(makeStart, TASK_GEN_IDES);
}
Task setupDevTask = makeTask(projectString(TASK_PROJECT_SETUP_DEV, patcher));
setupDevTask.dependsOn(setupTask, makeStart, TASK_GEN_IDES);
setupDevTask.dependsOn(eclipseRunClient, eclipseRunServer, ideaRunClient, ideaRunServer);
// fixe starts bieng created after the IDE thing
project.getTasks().getByName(TASK_GEN_IDES).mustRunAfter(makeStart);
/// TASKS THAT ARN'T PART OF THE SETUP
TaskSubprojectCall compile = makeTask(projectString(TASK_PROJECT_COMPILE, patcher), TaskSubprojectCall.class);
{
compile.setProjectDir(subWorkspace(patcher.getCapName()));
compile.setCallLine("jar");
compile.addInitScript(Resources.getResource(TaskSubprojectCall.class, "initscriptJar.gradle"));
compile.addReplacement("@RECOMP_DIR@", delayedFile(projectString(DIR_PROJECT_CACHE, patcher)));
compile.addReplacement("@JAR_NAME@", JAR_PROJECT_RECOMPILED.substring(DIR_PROJECT_CACHE.length() + 1));
compile.mustRunAfter(setupTask);
}
TaskExtractExcModifiers extractExc = makeTask(projectString(TASK_PROJECT_GEN_EXC, patcher), TaskExtractExcModifiers.class);
{
extractExc.setInJar(delayedFile(projectString(JAR_PROJECT_RECOMPILED, patcher)));
extractExc.setOutExc(delayedFile(projectString(EXC_PROJECT, patcher)));
extractExc.dependsOn(compile);
}
ExtractS2SRangeTask extractRangemap = makeTask(projectString(TASK_PROJECT_RANGEMAP, patcher), ExtractS2SRangeTask.class);
{
extractRangemap.addSource(patcher.getDelayedSourcesDir());
extractRangemap.addSource(subWorkspace(patcher.getCapName() + DIR_EXTRACTED_SRC));
extractRangemap.setRangeMap(delayedFile(projectString(RANGEMAP_PROJECT, patcher)));
extractRangemap.addLibs(project.getConfigurations().getByName(Constants.CONFIG_MC_DEPS));
extractRangemap.addLibs(delayedFile(projectString(JAR_PROJECT_RECOMPILED, patcher)));
extractRangemap.dependsOn(compile);
}
ApplyS2STask retromap = makeTask(projectString(TASK_PROJECT_RETROMAP, patcher), ApplyS2STask.class);
{
retromap.addSource(subWorkspace(patcher.getCapName() + DIR_EXTRACTED_SRC));
retromap.setOut(delayedFile(projectString(JAR_PROJECT_RETROMAPPED, patcher)));
retromap.addSrg(delayedFile(SRG_MCP_TO_SRG));
retromap.addExc(delayedFile(EXC_MCP));
retromap.addExc(delayedFile(EXC_SRG)); // just in case
retromap.setExcModifiers(delayedFile(projectString(EXC_PROJECT, patcher)));
retromap.setRangeMap(delayedFile(projectString(RANGEMAP_PROJECT, patcher)));
retromap.dependsOn(TASK_GENERATE_SRGS, extractExc, extractRangemap);
}
ApplyS2STask retromapNonMc = makeTask(projectString(TASK_PROJECT_RETRO_NONMC, patcher), ApplyS2STask.class);
{
retromapNonMc.addSource(patcher.getDelayedSourcesDir());
retromapNonMc.setOut(delayedFile(projectString(JAR_PROJECT_RETRO_NONMC, patcher)));
retromapNonMc.addSrg(delayedFile(SRG_MCP_TO_SRG));
retromapNonMc.addExc(delayedFile(EXC_MCP));
retromapNonMc.addExc(delayedFile(EXC_SRG)); // just in case
retromapNonMc.setExcModifiers(delayedFile(projectString(EXC_PROJECT, patcher)));
retromapNonMc.setRangeMap(delayedFile(projectString(RANGEMAP_PROJECT, patcher)));
retromapNonMc.dependsOn(TASK_GENERATE_SRGS, extractExc, extractRangemap);
}
}
protected void removeProject(PatcherProject patcher)
{
project.getTasks().remove(project.getTasks().getByName(projectString(TASK_PROJECT_REMAP_JAR, patcher)));
project.getTasks().remove(project.getTasks().getByName(projectString(TASK_PROJECT_EXTRACT_SRC, patcher)));
project.getTasks().remove(project.getTasks().getByName(projectString(TASK_PROJECT_EXTRACT_RES, patcher)));
project.getTasks().remove(project.getTasks().getByName(projectString(TASK_PROJECT_MAKE_START, patcher)));
project.getTasks().remove(project.getTasks().getByName(projectString(TASK_PROJECT_RUNE_CLIENT, patcher)));
project.getTasks().remove(project.getTasks().getByName(projectString(TASK_PROJECT_RUNE_SERVER, patcher)));
project.getTasks().remove(project.getTasks().getByName(projectString(TASK_PROJECT_RUNJ_CLIENT, patcher)));
project.getTasks().remove(project.getTasks().getByName(projectString(TASK_PROJECT_RUNJ_SERVER, patcher)));
((TaskGenSubprojects) project.getTasks().getByName(TASK_GEN_PROJECTS)).removeProject(patcher.getCapName());
project.getTasks().remove(project.getTasks().getByName(projectString(TASK_PROJECT_COMPILE, patcher)));
project.getTasks().remove(project.getTasks().getByName(projectString(TASK_PROJECT_GEN_EXC, patcher)));
project.getTasks().remove(project.getTasks().getByName(projectString(TASK_PROJECT_RANGEMAP, patcher)));
project.getTasks().remove(project.getTasks().getByName(projectString(TASK_PROJECT_RETROMAP, patcher)));
project.getTasks().remove(project.getTasks().getByName(projectString(TASK_PROJECT_RETRO_NONMC, patcher)));
}
public void afterEvaluate()
{
super.afterEvaluate();
// validate files
{
File versionJson = getExtension().getVersionJson();
File workspaceDir = getExtension().getWorkspaceDir();
if (workspaceDir == null)
{
throw new GradleConfigurationException("A workspaceDir must be specified! eg: minecraft { workspaceDir = 'someDir' }");
}
if (versionJson == null || !versionJson.exists())
{
throw new GradleConfigurationException("The versionJson could not be found! Are you sure its correct?");
}
if (((TaskProcessJson) project.getTasks().getByName(TASK_PROCESS_JSON)).isReleaseJsonNull())
{
throw new GradleConfigurationException("Release json not confgiured! add this to your buildscript: "
+ TASK_PROCESS_JSON + " { releaseJson = 'path/to/release.json' }");
}
if (Strings.isNullOrEmpty(getExtension().getInstallerVersion()) && getExtension().isBuildInstaller())
{
throw new GradleConfigurationException("You must specify the installerVersion in the minecraft block if you want to build an installer!");
}
}
// use versionJson stuff
{
File versionJson = getExtension().getVersionJson();
Version version = parseAndStoreVersion(versionJson, versionJson.getParentFile(), delayedFile(Constants.DIR_JSONS).call());
TaskGenSubprojects createProjects = (TaskGenSubprojects) project.getTasks().getByName(TASK_GEN_PROJECTS);
Set repos = Sets.newHashSet();
for (Library lib : version.getLibraries())
{
if (lib.applies() && lib.extract == null)
{
createProjects.addCompileDep(lib.getArtifactName());
// add repo for url if its not the MC repo, not maven central, and not already added
String url = lib.getUrl();
if (!url.contains("libraries.minecraft.net") && !url.contains("minecraft-libraries.s3.amazonaws.com") && !url.contains("maven.apache.org") && !repos.contains(url))
{
createProjects.addRepo("jsonRepo" + repos.size(), url);
// add it to here too!
this.addMavenRepo(project, "jsonRepo" + repos.size(), url);
repos.add(url);
}
}
}
}
// enable installer and userdev
{
Task build = project.getTasks().getByName(TASK_BUILD);
if (getExtension().isBuildUserdev())
{
build.dependsOn(TASK_BUILD_USERDEV);
}
if (getExtension().isBuildInstaller())
{
build.dependsOn(TASK_BUILD_INSTALLER);
}
}
List patchersList = sortByPatching(getExtension().getProjects());
// tasks to be configured
Task setupTask = project.getTasks().getByName(TASK_SETUP);
Task setupProjectTasks = project.getTasks().getByName(TASK_SETUP_PROJECTS);
Task genPatchesTask = project.getTasks().getByName(TASK_GEN_PATCHES);
DeobfuscateJar deobfJar = (DeobfuscateJar) project.getTasks().getByName(TASK_DEOBF);
TaskGenBinPatches binPatches = (TaskGenBinPatches) project.getTasks().getByName(TASK_GEN_BIN_PATCHES);
Jar outputJar = (Jar) project.getTasks().getByName(TASK_OUTPUT_JAR);
Zip resourceZip = (Zip) project.getTasks().getByName(TASK_COMBINE_RESOURCES);
TaskMergeFiles mergeFiles = (TaskMergeFiles) project.getTasks().getByName(TASK_MERGE_FILES);
List addedExcs = Lists.newArrayListWithCapacity(patchersList.size());
List addedSrgs = Lists.newArrayListWithCapacity(patchersList.size());
PatcherProject lastPatcher = null;
for (PatcherProject patcher : patchersList)
{
patcher.validate(); // validate project
if (patcher.isApplyMcpPatches())
{
PatchSourcesTask patch = (PatchSourcesTask) project.getTasks().getByName(projectString(TASK_PROJECT_PATCH, patcher));
RemapSources remap = (RemapSources) project.getTasks().getByName(projectString(TASK_PROJECT_REMAP_JAR, patcher));
// configure the patches to happen after remap
patch.dependsOn(remap);
patch.setInJar(delayedFile(projectString(JAR_PROJECT_REMAPPED, patcher)));
// configure patching input and injects
if (lastPatcher != null)
{
remap.dependsOn(projectString(TASK_PROJECT_REMAP_JAR, lastPatcher));
remap.setInJar(delayedFile(projectString(JAR_PROJECT_REMAPPED, lastPatcher)));
patch.addInject(lastPatcher.getDelayedSourcesDir());
patch.addInject(lastPatcher.getDelayedResourcesDir());
} else {
remap.setInJar(delayedFile(JAR_DECOMP_POST));
}
// configure extract tasks to extract patched
Object patched = delayedFile(projectString(JAR_PROJECT_PATCHED, patcher));
((ExtractTask) project.getTasks().getByName(projectString(TASK_PROJECT_EXTRACT_SRC, patcher))).from(patched);
((ExtractTask) project.getTasks().getByName(projectString(TASK_PROJECT_EXTRACT_RES, patcher))).from(patched);
}
else
{
PatchSourcesTask patch = (PatchSourcesTask) project.getTasks().getByName(projectString(TASK_PROJECT_PATCH, patcher));
RemapSources remap = (RemapSources) project.getTasks().getByName(projectString(TASK_PROJECT_REMAP_JAR, patcher));
// configure the patches to happen AFTER remap
remap.dependsOn(patch);
remap.setInJar(delayedFile(projectString(JAR_PROJECT_PATCHED, patcher)));
// configure patching input and injects
if (lastPatcher != null)
{
patch.dependsOn(projectString(TASK_PROJECT_PATCH, lastPatcher));
patch.setInJar(delayedFile(projectString(JAR_PROJECT_PATCHED, lastPatcher)));
patch.addInject(lastPatcher.getDelayedSourcesDir());
patch.addInject(lastPatcher.getDelayedResourcesDir());
} else {
patch.setInJar(delayedFile(JAR_DECOMP_POST));
}
Object remapped = delayedFile(projectString(JAR_PROJECT_REMAPPED, patcher));
((ExtractTask) project.getTasks().getByName(projectString(TASK_PROJECT_EXTRACT_SRC, patcher))).from(remapped);
((ExtractTask) project.getTasks().getByName(projectString(TASK_PROJECT_EXTRACT_RES, patcher))).from(remapped);
}
// get EXCs and SRGs for retromapping
ApplyS2STask retromap = (ApplyS2STask) project.getTasks().getByName(projectString(TASK_PROJECT_RETROMAP, patcher));
ApplyS2STask retromapNonMc = (ApplyS2STask) project.getTasks().getByName(projectString(TASK_PROJECT_RETRO_NONMC, patcher));
retromap.setS2sKeepImports(patcher.isS2sKeepImports());
retromapNonMc.setS2sKeepImports(patcher.isS2sKeepImports());
// add from previous projects
for (File f : addedExcs)
{
retromap.addExc(f);
retromapNonMc.addExc(f);
}
for (File f : addedSrgs)
{
retromap.addSrg(f);
retromapNonMc.addSrg(f);
}
// add from this project
for (File f : project.fileTree(patcher.getResourcesDir()).getFiles())
{
if (f.getName().endsWith(".exc"))
{
retromap.addExc(f);
retromapNonMc.addExc(f);
addedExcs.add(f);
mergeFiles.addExc(f);
}
else if (f.getName().endsWith(".srg"))
{
retromap.addSrg(f);
retromapNonMc.addSrg(f);
addedSrgs.add(f);
mergeFiles.addSrg(f);
}
else if (f.getName().endsWith("_at.cfg"))
{
// Add ATs for deobf in the same run.. why not...
deobfJar.addAt(f);
mergeFiles.addAt(f);
}
}
// create genPatches task for it.. if necessary
if (patcher.doesGenPatches())
{
TaskGenPatches genPatches = makeTask(projectString(TASK_PROJECT_GEN_PATCHES, patcher), TaskGenPatches.class);
genPatches.setPatchDir(patcher.getPatchDir());
genPatches.setOriginalPrefix(patcher.getPatchPrefixOriginal());
genPatches.setChangedPrefix(patcher.getPatchPrefixChanged());
//genPatches.getOutputs().upToDateWhen(CALL_FALSE);
genPatches.setGroup(GROUP_FG);
genPatches.setDescription("Generates patches for the '" + patcher.getName() + "' project");
// add to global task
genPatchesTask.dependsOn(genPatches);
if (patcher.isGenMcpPatches())
{
genPatches.addChangedSource(subWorkspace(patcher.getCapName() + DIR_EXTRACTED_SRC));
if ("clean".equals(patcher.getGenPatchesFrom().toLowerCase()))
{
genPatches.addOriginalSource(delayedFile(JAR_REMAPPED)); // SRG named vanilla..
}
else
{
PatcherProject genFrom = getExtension().getProjects().getByName(patcher.getGenPatchesFrom());
genPatches.addOriginalSource(delayedFile(projectString(JAR_PROJECT_REMAPPED, patcher)));
genPatches.addOriginalSource(genFrom.getDelayedSourcesDir());
}
}
else
{
genPatches.addChangedSource(delayedFile(projectString(JAR_PROJECT_RETROMAPPED, patcher)));
genPatches.dependsOn(projectString(TASK_PROJECT_RETROMAP, patcher));
if ("clean".equals(patcher.getGenPatchesFrom().toLowerCase()))
{
genPatches.addOriginalSource(delayedFile(JAR_DECOMP_POST)); // SRG named vanilla..
}
else
{
PatcherProject genFrom = getExtension().getProjects().getByName(patcher.getGenPatchesFrom());
genPatches.addOriginalSource(delayedFile(projectString(JAR_PROJECT_RETROMAPPED, genFrom)));
genPatches.addOriginalSource(delayedFile(projectString(JAR_PROJECT_RETRO_NONMC, genFrom)));
genPatches.dependsOn(projectString(TASK_PROJECT_RETROMAP, genFrom), projectString(TASK_PROJECT_RETRO_NONMC, genFrom));
}
}
}
// add patch sets to bin patches
binPatches.addPatchSet(patcher.getPatchDir());
// add resources to output
resourceZip.from(patcher.getDelayedResourcesDir());
outputJar.from(patcher.getDelayedResourcesDir());
// add task dependencies
setupProjectTasks.dependsOn(projectString(TASK_PROJECT_SETUP, patcher));
setupTask.dependsOn(projectString(TASK_PROJECT_SETUP_DEV, patcher));
// set last patcher..
lastPatcher = patcher;
}
// ------------------------------
// ------------------------------
// PACKAGING
PatcherProject patcher = patchersList.get(patchersList.size() - 1);
TaskReobfuscate reobf = (TaskReobfuscate) project.getTasks().getByName(TASK_REOBFUSCATE);
reobf.setInJar(delayedFile(projectString(JAR_PROJECT_RECOMPILED, patcher)));
reobf.dependsOn(projectString(TASK_PROJECT_COMPILE, patcher));
// Why regenerate patches from clean if the built project already has them?
// to strip the prefixes.. thats why...
TaskGenPatches userdevPatches = (TaskGenPatches) (project.getTasks().getByName(TASK_GEN_PATCHES_USERDEV));
userdevPatches.addChangedSource(delayedFile(projectString(JAR_PROJECT_RETROMAPPED, patcher)));
userdevPatches.dependsOn(TASK_POST_DECOMP, projectString(TASK_PROJECT_RETROMAP, patcher));
TaskExtractNew userdevSources = (TaskExtractNew) project.getTasks().getByName(TASK_EXTRACT_OBF_SOURCES);
userdevSources.addDirtySource(delayedFile(projectString(JAR_PROJECT_RETROMAPPED, patcher)));
userdevSources.addDirtySource(delayedFile(projectString(JAR_PROJECT_RETRO_NONMC, patcher)));
userdevSources.dependsOn(projectString(TASK_PROJECT_RETROMAP, patcher), projectString(TASK_PROJECT_RETRO_NONMC, patcher));
// add version to packaging tasks
ArchiveTaskHelper.setVersion(outputJar, project.getVersion().toString());
ArchiveTaskHelper.setVersion((Zip)project.getTasks().getByName(TASK_BUILD_USERDEV), project.getVersion().toString());
ArchiveTaskHelper.setVersion((Zip)project.getTasks().getByName(TASK_BUILD_INSTALLER), project.getVersion().toString());
// add them to the maven artifatcs
if (project.getPlugins().hasPlugin("maven"))
{
project.getArtifacts().add("archives", outputJar);
project.getArtifacts().add("archives", project.getTasks().getByName(TASK_BUILD_USERDEV));
project.getArtifacts().add("archives", project.getTasks().getByName(TASK_BUILD_INSTALLER));
}
}
/**
* Sorts the project into the list of patches on each other.
* Throws GradleConfigurationException if the projects cannot be fitted into the list.
* Doesnt support potential patching loops, but the clean project cant patch anything, so its unlikely to happen.
* @return list of sorted projects
*/
private List sortByPatching(NamedDomainObjectContainer projects)
{
// patcher->patched
BiMap tempMap = HashBiMap.create();
for (PatcherProject project : projects)
{
String patchAfter = project.getPatchAfter();
PatcherProject toPut;
if (patchAfter.equals("clean"))
{
toPut = null;
}
else
{
toPut = projects.findByName(patchAfter);
if (toPut == null)
throw new GradleConfigurationException("Project " + patchAfter + " does not exist! You cannot patch after it!");
if (toPut.isApplyMcpPatches() && !project.isApplyMcpPatches())
{
// its trying to apply SRG patches after a project that does MCP patches??
// IMPOSSIBRU!
throw new GradleConfigurationException("Project " + patchAfter + " applies SRG named patches, and is attempting to patch after a project that uses MCP named patches! THATS IMPOSSIBRU!");
}
}
try
{
tempMap.put(project, toPut);
}
catch (IllegalArgumentException e)
{
// must exist already.. thus a duplicate value..
throw new GradleConfigurationException("2 projects cannot patch after the same project '" + toPut == null ? "clean" : toPut.getName() + "'!");
}
}
// now patched->patcher
tempMap = tempMap.inverse();
ArrayList list = new ArrayList(projects.size());
PatcherProject key = tempMap.remove(null); // null is clean
while (key != null)
{
list.add(key);
key = tempMap.remove(key);
}
return list;
}
private Closure subWorkspace(String path)
{
return getExtension().getDelayedSubWorkspaceDir(path);
}
private String projectString(String str, PatcherProject project)
{
return str.replace("{CAPNAME}", project.getCapName()).replace("{NAME}", project.getName());
}
}