Package net.minecraftforge.gradle.user

Source Code of net.minecraftforge.gradle.user.UserBasePlugin

package net.minecraftforge.gradle.user;

import static net.minecraftforge.gradle.common.Constants.ASSETS;
import static net.minecraftforge.gradle.common.Constants.FERNFLOWER;
import static net.minecraftforge.gradle.common.Constants.JAR_CLIENT_FRESH;
import static net.minecraftforge.gradle.common.Constants.JAR_MERGED;
import static net.minecraftforge.gradle.common.Constants.JAR_SERVER_FRESH;
import static net.minecraftforge.gradle.user.UserConstants.ASTYLE_CFG;
import static net.minecraftforge.gradle.user.UserConstants.CLASSIFIER_DECOMPILED;
import static net.minecraftforge.gradle.user.UserConstants.CLASSIFIER_DEOBF_SRG;
import static net.minecraftforge.gradle.user.UserConstants.CLASSIFIER_SOURCES;
import static net.minecraftforge.gradle.user.UserConstants.CONFIG_DEPS;
import static net.minecraftforge.gradle.user.UserConstants.CONFIG_MC;
import static net.minecraftforge.gradle.user.UserConstants.CONFIG_NATIVES;
import static net.minecraftforge.gradle.user.UserConstants.CONFIG_USERDEV;
import static net.minecraftforge.gradle.user.UserConstants.DEOBF_MCP_SRG;
import static net.minecraftforge.gradle.user.UserConstants.DEOBF_SRG_SRG;
import static net.minecraftforge.gradle.user.UserConstants.DIRTY_DIR;
import static net.minecraftforge.gradle.user.UserConstants.EXC_JSON;
import static net.minecraftforge.gradle.user.UserConstants.EXC_MCP;
import static net.minecraftforge.gradle.user.UserConstants.EXC_SRG;
import static net.minecraftforge.gradle.user.UserConstants.FIELD_CSV;
import static net.minecraftforge.gradle.user.UserConstants.MCP_PATCH_DIR;
import static net.minecraftforge.gradle.user.UserConstants.MERGE_CFG;
import static net.minecraftforge.gradle.user.UserConstants.METHOD_CSV;
import static net.minecraftforge.gradle.user.UserConstants.NATIVES_DIR;
import static net.minecraftforge.gradle.user.UserConstants.PACKAGED_EXC;
import static net.minecraftforge.gradle.user.UserConstants.PACKAGED_SRG;
import static net.minecraftforge.gradle.user.UserConstants.PARAM_CSV;
import static net.minecraftforge.gradle.user.UserConstants.RECOMP_CLS_DIR;
import static net.minecraftforge.gradle.user.UserConstants.RECOMP_SRC_DIR;
import static net.minecraftforge.gradle.user.UserConstants.REOBF_NOTCH_SRG;
import static net.minecraftforge.gradle.user.UserConstants.REOBF_SRG;
import static net.minecraftforge.gradle.user.UserConstants.SOURCES_DIR;
import groovy.lang.Closure;
import groovy.util.Node;
import groovy.util.XmlParser;
import groovy.xml.XmlUtil;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import joptsimple.internal.Strings;
import net.minecraftforge.gradle.common.BasePlugin;
import net.minecraftforge.gradle.delayed.DelayedFile;
import net.minecraftforge.gradle.json.JsonFactory;
import net.minecraftforge.gradle.tasks.CopyAssetsTask;
import net.minecraftforge.gradle.tasks.DecompileTask;
import net.minecraftforge.gradle.tasks.GenSrgTask;
import net.minecraftforge.gradle.tasks.MergeJarsTask;
import net.minecraftforge.gradle.tasks.ProcessJarTask;
import net.minecraftforge.gradle.tasks.RemapSourcesTask;
import net.minecraftforge.gradle.tasks.abstractutil.ExtractTask;
import net.minecraftforge.gradle.tasks.user.SourceCopyTask;
import net.minecraftforge.gradle.tasks.user.reobf.ArtifactSpec;
import net.minecraftforge.gradle.tasks.user.reobf.ReobfTask;

import org.gradle.api.Action;
import org.gradle.api.DefaultTask;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.XmlProvider;
import org.gradle.api.artifacts.Configuration.State;
import org.gradle.api.artifacts.dsl.DependencyHandler;
import org.gradle.api.execution.TaskExecutionGraph;
import org.gradle.api.internal.plugins.DslObject;
import org.gradle.api.logging.Logger;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.GroovySourceSet;
import org.gradle.api.tasks.JavaExec;
import org.gradle.api.tasks.ScalaSourceSet;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.bundling.Jar;
import org.gradle.api.tasks.compile.GroovyCompile;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.api.tasks.scala.ScalaCompile;
import org.gradle.listener.ActionBroadcast;
import org.gradle.plugins.ide.eclipse.model.Classpath;
import org.gradle.plugins.ide.eclipse.model.ClasspathEntry;
import org.gradle.plugins.ide.eclipse.model.EclipseModel;
import org.gradle.plugins.ide.eclipse.model.Library;
import org.gradle.plugins.ide.idea.model.IdeaModel;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.google.common.base.Joiner;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Files;

public abstract class UserBasePlugin<T extends UserExtension> extends BasePlugin<T>
{
    @SuppressWarnings("serial")
    @Override
    public void applyPlugin()
    {
        this.applyExternalPlugin("java");
        this.applyExternalPlugin("maven");
        this.applyExternalPlugin("eclipse");
        this.applyExternalPlugin("idea");
       
        hasScalaBefore = project.getPlugins().hasPlugin("scala");
        hasGroovyBefore = project.getPlugins().hasPlugin("groovy");
       
        configureDeps();
        configureCompilation();
        fixEclipseNatives();
        configureIntellij();
       
        // create basic tasks.
        tasks();
       
        // create lifecycle tasks.
       
        Task task = makeTask("setupCIWorkspace", DefaultTask.class);
        task.dependsOn("genSrgs", "deobfBinJar");
        task.setDescription("Sets up the bare minimum to build a minecraft mod. Idea for CI servers");
        task.setGroup("ForgeGradle");
        //configureCISetup(task);

        task = makeTask("setupDevWorkspace", DefaultTask.class);
        task.dependsOn("genSrgs", "deobfBinJar", "copyAssets", "extractNatives");
        task.setDescription("CIWorkspace + natives and assets to run and test Minecraft");
        task.setGroup("ForgeGradle");
        //configureDevSetup(task);

        task = makeTask("setupDecompWorkspace", DefaultTask.class);
        task.dependsOn("genSrgs", "copyAssets", "extractNatives", "repackMinecraft");
        task.setDescription("DevWorkspace + the deobfuscated Minecraft source linked as a source jar.");
        task.setGroup("ForgeGradle");
        //configureDecompSetup(task);
       
        project.getGradle().getTaskGraph().whenReady(new Closure<Object>(this, null) {
            @Override
            public Object call()
            {
                TaskExecutionGraph graph = project.getGradle().getTaskGraph();
                String path = project.getPath();
               
                if (graph.hasTask(path + "setupDecompWorkspace"))
                {
                    getExtension().setDecomp();
                    setMinecraftDeps(true, false);
                }
                return null;
            }
           
            @Override
            public Object call(Object obj)
            {
                return call();
            }
           
            @Override
            public Object call(Object... obj)
            {
                return call();
            }
        });
    }
   
    private boolean hasAppliedJson = false;
    private boolean hasScalaBefore = false;
    private boolean hasGroovyBefore = false;
   
    /**
     * may not include delayed tokens.
     */
    public abstract String getApiName();
    /**
     * Name of the source dependency.  eg: forgeSrc
     * may not include delayed tokens.
     */
    protected abstract String getSrcDepName();
    /**
     * Name of the source dependency.  eg: forgeBin
     * may not include delayed tokens.
     */
    protected abstract String getBinDepName();
   
    /**
     * May invoke the extension object, or be hardcoded.
     * may not include delayed tokens.
     */
    protected abstract boolean hasApiVersion();
    /**
     * May invoke the extension object, or be hardcoded.
     * may not include delayed tokens.
     */
    protected abstract String getApiVersion(T exten);
    /**
     * May invoke the extension object, or be hardcoded.
     * may not include delayed tokens.
     */
    protected abstract String getMcVersion(T exten);
    /**
     * May invoke the extension object, or be hardcoded.
     * This unlike the others, is evaluated as a delayed file, and may contain various tokens including:
     * {API_NAME} {API_VERSION} {MC_VERSION}
     */
    protected abstract String getApiCacheDir(T exten);
    /**
     * May invoke the extension object, or be hardcoded.
     * This unlike the others, is evaluated as a delayed file, and may contain various tokens including:
     * {API_NAME} {API_VERSION} {MC_VERSION}
     */
    protected abstract String getSrgCacheDir(T exten);
    /**
     * May invoke the extension object, or be hardcoded.
     * This unlike the others, is evaluated as a delayed file, and may contain various tokens including:
     * {API_NAME} {API_VERSION} {MC_VERSION}
     */
    protected abstract String getUserDevCacheDir(T exten);
    /**
     * This unlike the others, is evaluated as a delayed string, and may contain various tokens including:
     * {API_NAME} {API_VERSION} {MC_VERSION}
     */
    protected abstract String getUserDev();
   
    /**
     * For run configurations
     */
    protected abstract String getClientRunClass();
    /**
     * For run configurations
     */
    protected abstract Iterable<String> getClientRunArgs();
    /**
     * For run configurations
     */
    protected abstract String getServerRunClass();
    /**
     * For run configurations
     */
    protected abstract Iterable<String> getServerRunArgs();
   
//    protected abstract void configureCISetup(Task task);
//    protected abstract void configureDevSetup(Task task);
//    protected abstract void configureDecompSetup(Task task);
   
    @Override
    public String resolve(String pattern, Project project, T exten)
    {
        pattern = pattern.replace("{USER_DEV}", this.getUserDevCacheDir(exten));
        pattern = pattern.replace("{SRG_DIR}", this.getSrgCacheDir(exten));
        pattern = pattern.replace("{API_CACHE_DIR}", this.getApiCacheDir(exten));
        pattern = pattern.replace("{MC_VERSION}", getMcVersion(exten));
        pattern = super.resolve(pattern, project, exten);
        if (hasApiVersion())
            pattern = pattern.replace("{API_VERSION}", getApiVersion(exten));
        pattern = pattern.replace("{API_NAME}", getApiName());
        return pattern;
    }
   
    protected void configureDeps()
    {
        // create configs
        project.getConfigurations().create(CONFIG_USERDEV);
        project.getConfigurations().create(CONFIG_NATIVES);
        project.getConfigurations().create(CONFIG_DEPS);
        project.getConfigurations().create(CONFIG_MC);

        // special userDev stuff
        ExtractTask extractUserDev = makeTask("extractUserDev", ExtractTask.class);
        extractUserDev.into(delayedFile("{USER_DEV}"));
        extractUserDev.setDoesCache(true);
        extractUserDev.doLast(new Action<Task>()
        {
            @Override
            public void execute(Task arg0)
            {
                readAndApplyJson(getDevJson().call(), CONFIG_DEPS, CONFIG_NATIVES, arg0.getLogger());
            }
        });

        // special native stuff
        ExtractTask extractNatives = makeTask("extractNatives", ExtractTask.class);
        extractNatives.into(delayedFile(NATIVES_DIR));
        extractNatives.dependsOn("extractUserDev");

        // extra libs folder.
        project.getDependencies().add("compile", project.fileTree("libs"));

        // make MC dependencies into normal compile classpath
        project.getDependencies().add("compile", project.getConfigurations().getByName(CONFIG_DEPS));
        project.getDependencies().add("compile", project.getConfigurations().getByName(CONFIG_MC));
    }
   
    /**
     * This mod adds the API sourceSet, and correctly configures the
     */
    protected void configureCompilation()
    {
        // get conventions
        JavaPluginConvention javaConv = (JavaPluginConvention) project.getConvention().getPlugins().get("java");

        SourceSet main = javaConv.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME);
        SourceSet test = javaConv.getSourceSets().getByName(SourceSet.TEST_SOURCE_SET_NAME);
        SourceSet api = javaConv.getSourceSets().create("api");

        // set the Source
        javaConv.setSourceCompatibility("1.6");
        javaConv.setTargetCompatibility("1.6");

        main.setCompileClasspath(main.getCompileClasspath().plus(api.getOutput()));
        test.setCompileClasspath(test.getCompileClasspath().plus(api.getOutput()));

        project.getConfigurations().getByName("apiCompile").extendsFrom(project.getConfigurations().getByName("compile"));
        project.getConfigurations().getByName("testCompile").extendsFrom(project.getConfigurations().getByName("apiCompile"));
    }
   
    private void readAndApplyJson(File file, String depConfig, String nativeConfig, Logger log)
    {
        if (version == null)
        {
            try
            {
                version = JsonFactory.loadVersion(file);
            }
            catch (Exception e)
            {
                log.error("" + file + " could not be parsed");
                Throwables.propagate(e);
            }
        }

        if (hasAppliedJson)
            return;

        // apply the dep info.
        DependencyHandler handler = project.getDependencies();

        // actual dependencies
        if (project.getConfigurations().getByName(depConfig).getState() == State.UNRESOLVED)
        {
            for (net.minecraftforge.gradle.json.version.Library lib : version.getLibraries())
            {
                if (lib.natives == null)
                    handler.add(depConfig, lib.getArtifactName());
            }
        }
        else
            log.info("RESOLVED: " + depConfig);

        // the natives
        if (project.getConfigurations().getByName(nativeConfig).getState() == State.UNRESOLVED)
        {
            for (net.minecraftforge.gradle.json.version.Library lib : version.getLibraries())
            {
                if (lib.natives != null)
                    handler.add(nativeConfig, lib.getArtifactName());
            }
        }
        else
            log.info("RESOLVED: " + nativeConfig);

        hasAppliedJson = true;

        // add stuff to the natives task thing..
        // extract natives
        ExtractTask task = (ExtractTask) project.getTasks().findByName("extractNatives");
        for (File dep : project.getConfigurations().getByName(CONFIG_NATIVES).getFiles())
        {
            log.info("ADDING NATIVE: " + dep.getPath());
            task.from(delayedFile(dep.getAbsolutePath()));
            task.exclude("META-INF/**", "META-INF/**");
        }
    }

    @SuppressWarnings({ "unchecked" })
    protected void fixEclipseNatives()
    {
        EclipseModel eclipseConv = (EclipseModel) project.getExtensions().getByName("eclipse");

        eclipseConv.getClasspath().setDownloadJavadoc(true);
        eclipseConv.getClasspath().setDownloadSources(true);
        ((ActionBroadcast<Classpath>) eclipseConv.getClasspath().getFile().getWhenMerged()).add(new Action<Classpath>()
        {
            @Override
            public void execute(Classpath classpath)
            {
                String natives = delayedString(NATIVES_DIR).call().replace('\\', '/');
                for (ClasspathEntry e : classpath.getEntries())
                {
                    if (e instanceof Library)
                    {
                        Library lib = (Library) e;
                        if (lib.getPath().contains("lwjg") || lib.getPath().contains("jinput"))
                        {
                            lib.setNativeLibraryLocation(natives);
                        }
                    }
                }
            }
        });

        Task task = makeTask("afterEclipseImport", DefaultTask.class);
        task.doLast(new Action<Object>() {
            public void execute(Object obj)
            {
                try
                {
                    Node root = new XmlParser().parseText(Files.toString(project.file(".classpath"), Charset.defaultCharset()));

                    HashMap<String, String> map = new HashMap<String, String>();
                    map.put("name", "org.eclipse.jdt.launching.CLASSPATH_ATTR_LIBRARY_PATH_ENTRY");
                    map.put("value", delayedString(NATIVES_DIR).call());

                    for (Node child : (List<Node>) root.children())
                    {
                        if (child.attribute("path").equals("org.springsource.ide.eclipse.gradle.classpathcontainer"))
                        {
                            child.appendNode("attributes").appendNode("attribute", map);
                            break;
                        }
                    }

                    String result = XmlUtil.serialize(root);

                    project.getLogger().lifecycle(result);
                    Files.write(result, project.file(".classpath"), Charset.defaultCharset());

                }
                catch (Exception e)
                {
                    e.printStackTrace();
                    return;
                }
            }
        });
    }
   
    @SuppressWarnings("serial")
    protected void configureIntellij()
    {
        IdeaModel ideaConv = (IdeaModel) project.getExtensions().getByName("idea");

        ideaConv.getModule().getExcludeDirs().addAll(project.files(".gradle", "build", ".idea").getFiles());
        ideaConv.getModule().setDownloadJavadoc(true);
        ideaConv.getModule().setDownloadSources(true);

        Task task = makeTask("genIntellijRuns", DefaultTask.class);
        task.doLast(new Action<Task>() {
            @Override
            public void execute(Task task)
            {
                try
                {
                    String module = task.getProject().getProjectDir().getCanonicalPath();
                    File file = project.file(".idea/workspace.xml");
                    if (!file.exists())
                        throw new RuntimeException("Only run this task after importing a build.gradle file into intellij!");

                    DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
                    DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
                    Document doc = docBuilder.parse(file);

                    injectIntellijRuns(doc, module);

                    // write the content into xml file
                    TransformerFactory transformerFactory = TransformerFactory.newInstance();
                    Transformer transformer = transformerFactory.newTransformer();
                    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
                    transformer.setOutputProperty(OutputKeys.METHOD, "xml");
                    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
                    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
                    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

                    DOMSource source = new DOMSource(doc);
                    StreamResult result = new StreamResult(file);
                    //StreamResult result = new StreamResult(System.out);

                    transformer.transform(source, result);
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        });

        if (ideaConv.getWorkspace().getIws() == null)
            return;

        ideaConv.getWorkspace().getIws().withXml(new Closure<Object>(this, null)
        {
            public Object call(Object... obj)
            {
                Element root = ((XmlProvider) this.getDelegate()).asElement();
                Document doc = root.getOwnerDocument();
                try
                {
                    injectIntellijRuns(doc, project.getProjectDir().getCanonicalPath());
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }

                return null;
            }
        });
    }
   
    public final void injectIntellijRuns(Document doc, String module) throws DOMException, IOException
    {
        Element root = null;

        {
            NodeList list = doc.getElementsByTagName("component");
            for (int i = 0; i < list.getLength(); i++)
            {
                Element e = (Element) list.item(i);
                if ("RunManager".equals(e.getAttribute("name")))
                {
                    root = e;
                    break;
                }
            }
        }

        String natives = delayedFile(NATIVES_DIR).call().getCanonicalPath().replace(module, "$PROJECT_DIR$");

        String[][] config = new String[][]
        {
                new String[]
                {
                        "Minecraft Client",
                        getClientRunClass(),
                        "-Xincgc -Xmx1024M -Xms1024M -Djava.library.path=\"" + natives + "\" -Dfml.ignoreInvalidMinecraftCertificates=true",
                        Joiner.on(' ').join(getClientRunArgs())
                },
                new String[]
                {
                        "Minecraft Server",
                        getServerRunClass(),
                        "-Xincgc -Dfml.ignoreInvalidMinecraftCertificates=true",
                        Joiner.on(' ').join(getServerRunArgs())
                }
        };

        for (String[] data : config)
        {
            Element child = add(root, "configuration",
                    "default", "false",
                    "name", data[0],
                    "type", "Application",
                    "factoryName", "Application",
                    "default", "false");

            add(child, "extension",
                    "name", "coverage",
                    "enabled", "false",
                    "sample_coverage", "true",
                    "runner", "idea");
            add(child, "option", "name", "MAIN_CLASS_NAME", "value", data[1]);
            add(child, "option", "name", "VM_PARAMETERS", "value", data[2]);
            add(child, "option", "name", "PROGRAM_PARAMETERS", "value", data[3]);
            add(child, "option", "name", "WORKING_DIRECTORY", "value", "file://" + delayedFile("{ASSET_DIR}").call().getParentFile().getCanonicalPath().replace(module, "$PROJECT_DIR$"));
            add(child, "option", "name", "ALTERNATIVE_JRE_PATH_ENABLED", "value", "false");
            add(child, "option", "name", "ALTERNATIVE_JRE_PATH", "value", "");
            add(child, "option", "name", "ENABLE_SWING_INSPECTOR", "value", "false");
            add(child, "option", "name", "ENV_VARIABLES");
            add(child, "option", "name", "PASS_PARENT_ENVS", "value", "true");
            add(child, "module", "name", ((IdeaModel) project.getExtensions().getByName("idea")).getModule().getName());
            add(child, "envs");
            add(child, "RunnerSettings", "RunnerId", "Run");
            add(child, "ConfigurationWrapper", "RunnerId", "Run");
            add(child, "method");
        }
    }
   
    private Element add(Element parent, String name, String... values)
    {
        Element e = parent.getOwnerDocument().createElement(name);
        for (int x = 0; x < values.length; x += 2)
        {
            e.setAttribute(values[x], values[x + 1]);
        }
        parent.appendChild(e);
        return e;
    }
   
    private void tasks()
    {
        {
            CopyAssetsTask task = makeTask("copyAssets", CopyAssetsTask.class);
            task.setAssetsDir(delayedFile(ASSETS));
            task.setOutputDir(delayedFile("{ASSET_DIR}"));
            task.setAssetIndex(getAssetIndexClosure());
            task.dependsOn("getAssets");
        }
       
        {
            GenSrgTask task = makeTask("genSrgs", GenSrgTask.class);
            task.setInSrg(delayedFile(PACKAGED_SRG));
            task.setInExc(delayedFile(PACKAGED_EXC));
            task.setMethodsCsv(delayedFile(METHOD_CSV));
            task.setFieldsCsv(delayedFile(FIELD_CSV));
            task.setNotchToSrg(delayedFile(DEOBF_SRG_SRG));
            task.setNotchToMcp(delayedFile(DEOBF_MCP_SRG));
            task.setMcpToSrg(delayedFile(REOBF_SRG));
            task.setMcpToNotch(delayedFile(REOBF_NOTCH_SRG));
            task.setSrgExc(delayedFile(EXC_SRG));
            task.setMcpExc(delayedFile(EXC_MCP));
            task.dependsOn("extractUserDev");
        }
       
        {
            MergeJarsTask task = makeTask("mergeJars", MergeJarsTask.class);
            task.setClient(delayedFile(JAR_CLIENT_FRESH));
            task.setServer(delayedFile(JAR_SERVER_FRESH));
            task.setOutJar(delayedFile(JAR_MERGED));
            task.setMergeCfg(delayedFile(MERGE_CFG));
            task.dependsOn("extractUserDev", "downloadClient", "downloadServer");
        }

        {
            String name = getBinDepName() + "-" + (hasApiVersion() ? "{API_VERSION}" : "{MC_VERSION}") + ".jar";
           
            ProcessJarTask task = makeTask("deobfBinJar", ProcessJarTask.class);
            task.setSrg(delayedFile(DEOBF_MCP_SRG));
            task.setExceptorJson(delayedFile(EXC_JSON));
            task.setExceptorCfg(delayedFile(EXC_MCP));
            task.setFieldCsv(delayedFile(FIELD_CSV));
            task.setMethodCsv(delayedFile(METHOD_CSV));
            task.setInJar(delayedFile(JAR_MERGED));
            task.setOutCleanJar(delayedFile("{API_CACHE_DIR}/" + name));
            task.setOutDirtyJar(delayedFile(DIRTY_DIR + "/" + name));
            task.setApplyMarkers(false);
            task.setStripSynthetics(true);
            configureDeobfuscation(task);
            task.dependsOn("downloadMcpTools", "mergeJars", "genSrgs");
        }

        {
            String name = "{API_NAME}-" + (hasApiVersion() ? "{API_VERSION}" : "{MC_VERSION}") + "-"+ CLASSIFIER_DEOBF_SRG +".jar";
           
            ProcessJarTask task = makeTask("deobfuscateJar", ProcessJarTask.class);
            task.setSrg(delayedFile(DEOBF_SRG_SRG));
            task.setExceptorJson(delayedFile(EXC_JSON));
            task.setExceptorCfg(delayedFile(EXC_SRG));
            task.setInJar(delayedFile(JAR_MERGED));
            task.setOutCleanJar(delayedFile("{API_CACHE_DIR}/" + name));
            task.setOutDirtyJar(delayedFile(DIRTY_DIR + "/" + name));
            task.setApplyMarkers(true);
            configureDeobfuscation(task);
            task.dependsOn("downloadMcpTools", "mergeJars", "genSrgs");
        }

        {
            ReobfTask task = makeTask("reobf", ReobfTask.class);
            task.dependsOn("genSrgs");
            task.setExceptorCfg(delayedFile(EXC_SRG));
            task.setSrg(delayedFile(REOBF_SRG));
            task.setFieldCsv(delayedFile(FIELD_CSV));
            task.setFieldCsv(delayedFile(METHOD_CSV));
            task.reobf(project.getTasks().getByName("jar"), new Action<ArtifactSpec>()
            {
                @Override
                public void execute(ArtifactSpec arg0)
                {
                    JavaPluginConvention javaConv = (JavaPluginConvention) project.getConvention().getPlugins().get("java");
                    arg0.setClasspath(javaConv.getSourceSets().getByName("main").getCompileClasspath());
                }

            });
           
            task.mustRunAfter("test");
            project.getTasks().getByName("assemble").dependsOn(task);
            project.getTasks().getByName("uploadArchives").dependsOn(task);
        }
       
        createPostDecompTasks();
        createExecTasks();
        createSourceCopyTasks();
    }
   
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private final void createPostDecompTasks()
    {
        DelayedFile decompOut = delayedDirtyFile(null, CLASSIFIER_DECOMPILED, "jar");
        DelayedFile remapped = delayedDirtyFile(getSrcDepName(), CLASSIFIER_SOURCES, "jar");
        final DelayedFile recomp = delayedDirtyFile(getSrcDepName(), null, "jar");
        final DelayedFile recompSrc = delayedFile(RECOMP_SRC_DIR);
        final DelayedFile recompCls = delayedFile(RECOMP_CLS_DIR);
       
        DecompileTask decomp = makeTask("decompile", DecompileTask.class);
        {
            decomp.setInJar(delayedDirtyFile(null, CLASSIFIER_DEOBF_SRG, "jar"));
            decomp.setOutJar(decompOut);
            decomp.setFernFlower(delayedFile(FERNFLOWER));
            decomp.setPatch(delayedFile(MCP_PATCH_DIR));
            decomp.setAstyleConfig(delayedFile(ASTYLE_CFG));
            decomp.dependsOn("downloadMcpTools", "deobfuscateJar", "genSrgs");
        }

        // Remap to MCP names
        RemapSourcesTask remap = makeTask("remapJar", RemapSourcesTask.class);
        {
            remap.setInJar(decompOut);
            remap.setOutJar(remapped);
            remap.setFieldsCsv(delayedFile(FIELD_CSV));
            remap.setMethodsCsv(delayedFile(METHOD_CSV));
            remap.setParamsCsv(delayedFile(PARAM_CSV));
            remap.setDoesJavadocs(true);
            remap.dependsOn(decomp);
        }

        Spec onlyIfCheck = new Spec() {
            @Override
            public boolean isSatisfiedBy(Object obj)
            {
                boolean didWork = ((Task) obj).dependsOnTaskDidWork();
                boolean exists = recomp.call().exists();
                if (!exists)
                    return true;
                else
                    return didWork;
            }
        };

        ExtractTask extract = makeTask("extractMinecraftSrc", ExtractTask.class);
        {
            extract.from(remapped);
            extract.into(recompSrc);
            extract.setIncludeEmptyDirs(false);
            extract.dependsOn(remap);

            extract.onlyIf(onlyIfCheck);
        }

        JavaCompile recompTask = makeTask("recompMinecraft", JavaCompile.class);
        {
            recompTask.setSource(recompSrc);
            recompTask.setSourceCompatibility("1.6");
            recompTask.setTargetCompatibility("1.6");
            recompTask.setClasspath(project.getConfigurations().getByName(CONFIG_DEPS));
            recompTask.dependsOn(extract);

            recompTask.onlyIf(onlyIfCheck);
        }

        Jar repackageTask = makeTask("repackMinecraft", Jar.class);
        {
            repackageTask.from(recompSrc);
            repackageTask.from(recompCls);
            repackageTask.exclude("*.java", "**/*.java", "**.java");
            repackageTask.dependsOn(recompTask);
           
            // file output configuration done in the delayed configuration.

            repackageTask.onlyIf(onlyIfCheck);
        }
    }
   
    private final void createExecTasks()
    {
        JavaExec exec = makeTask("runClient", JavaExec.class);
        {
            exec.setMain(getClientRunClass());
            exec.jvmArgs("-Xincgc", "-Xmx1024M", "-Xms1024M", "-Dfml.ignoreInvalidMinecraftCertificates=true");
            exec.args(getClientRunArgs());
            exec.workingDir(delayedFile("{ASSET_DIR}/.."));
            exec.setStandardOutput(System.out);
            exec.setErrorOutput(System.err);

            exec.setGroup("ForgeGradle");
            exec.setDescription("Runs the Minecraft client");
        }

        exec = makeTask("runServer", JavaExec.class);
        {
            exec.setMain(getServerRunClass());
            exec.jvmArgs("-Xincgc", "-Dfml.ignoreInvalidMinecraftCertificates=true");
            exec.workingDir(delayedFile("{ASSET_DIR}/.."));
            exec.args(getServerRunArgs());
            exec.setStandardOutput(System.out);
            exec.setStandardInput(System.in);
            exec.setErrorOutput(System.err);

            exec.setGroup("ForgeGradle");
            exec.setDescription("Runs the Minecraft Server");
        }

        exec = makeTask("debugClient", JavaExec.class);
        {
            exec.setMain(getClientRunClass());
            exec.jvmArgs("-Xincgc", "-Xmx1024M", "-Xms1024M", "-Dfml.ignoreInvalidMinecraftCertificates=true");
            exec.args(getClientRunArgs());
            exec.workingDir(delayedFile("{ASSET_DIR}/.."));
            exec.setStandardOutput(System.out);
            exec.setErrorOutput(System.err);
            exec.setDebug(true);

            exec.setGroup("ForgeGradle");
            exec.setDescription("Runs the Minecraft client in debug mode");
        }

        exec = makeTask("debugServer", JavaExec.class);
        {
            exec.setMain(getServerRunClass());
            exec.jvmArgs("-Xincgc", "-Dfml.ignoreInvalidMinecraftCertificates=true");
            exec.workingDir(delayedFile("{ASSET_DIR}/.."));
            exec.args(getServerRunArgs());
            exec.setStandardOutput(System.out);
            exec.setStandardInput(System.in);
            exec.setErrorOutput(System.err);
            exec.setDebug(true);

            exec.setGroup("ForgeGradle");
            exec.setDescription("Runs the Minecraft serevr in debug mode");
        }
    }
   
    private final void createSourceCopyTasks()
    {
        JavaPluginConvention javaConv = (JavaPluginConvention) project.getConvention().getPlugins().get("java");
        SourceSet main = javaConv.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME);

        // do the special source moving...
        SourceCopyTask task;

        // main
        {
            DelayedFile dir = delayedFile(SOURCES_DIR + "/java");
           
            task = makeTask("sourceMainJava", SourceCopyTask.class);
            task.setSource(main.getJava());
            task.setOutput(dir);

            JavaCompile compile = (JavaCompile) project.getTasks().getByName(main.getCompileJavaTaskName());
            compile.dependsOn("sourceMainJava");
            compile.setSource(dir);
        }

        // scala!!!
        if (project.getPlugins().hasPlugin("scala"))
        {
            ScalaSourceSet set = (ScalaSourceSet) new DslObject(main).getConvention().getPlugins().get("scala");
            DelayedFile dir = delayedFile(SOURCES_DIR + "/scala");

            task = makeTask("sourceMainScala", SourceCopyTask.class);
            task.setSource(set.getScala());
            task.setOutput(dir);

            ScalaCompile compile = (ScalaCompile) project.getTasks().getByName(main.getCompileTaskName("scala"));
            compile.dependsOn("sourceMainScala");
            compile.setSource(dir);
        }

        // groovy!!!
        if (project.getPlugins().hasPlugin("groovy"))
        {
            GroovySourceSet set = (GroovySourceSet) new DslObject(main).getConvention().getPlugins().get("groovy");
            DelayedFile dir = delayedFile(SOURCES_DIR + "/groovy");

            task = makeTask("sourceMainGroovy", SourceCopyTask.class);
            task.setSource(set.getGroovy());
            task.setOutput(dir);

            GroovyCompile compile = (GroovyCompile) project.getTasks().getByName(main.getCompileTaskName("groovy"));
            compile.dependsOn("sourceMainGroovy");
            compile.setSource(dir);
        }
    }
   
    @Override
    public final void afterEvaluate()
    {
        super.afterEvaluate();
       
        {
            String version = getMcVersion(getExtension());
            if (hasApiVersion())
                version = getApiVersion(getExtension());
           
            doVersionChecks(version);
        }
       
        // ensure plugin application sequence.. groovy or scala or wtvr first, then the forge/fml/liteloader plugins
        if (!hasScalaBefore && project.getPlugins().hasPlugin("scala"))
            throw new RuntimeException(delayedString("You have applied the 'scala' plugin after '{API_NAME}', you must apply it before.").call());
        if (!hasGroovyBefore && project.getPlugins().hasPlugin("groovy"))
            throw new RuntimeException(delayedString("You have applied the 'groovy' plugin after '{API_NAME}', you must apply it before.").call());
       
        project.getDependencies().add(CONFIG_USERDEV, delayedString(getUserDev()).call() + ":userdev");

        // grab the json && read dependencies
        if (getDevJson().call().exists())
        {
            readAndApplyJson(getDevJson().call(), CONFIG_DEPS, CONFIG_NATIVES, project.getLogger());
        }
       
        delayedTaskConfig();
       
        // add MC repo.
        final String repoDir = delayedDirtyFile("this", "doesnt", "matter").call().getParentFile().getAbsolutePath();
        project.allprojects(new Action<Project>() {
            public void execute(Project proj)
            {
                addFlatRepo(proj, getApiName()+"FlatRepo", repoDir);
                proj.getLogger().info("Adding repo to " + proj.getPath() + " >> " + repoDir);
            }
        });
       
        // check for decompilation status.. has decompiled or not etc
        final File decompFile = delayedDirtyFile(getSrcDepName(), CLASSIFIER_SOURCES, "jar").call();
        if (decompFile.exists())
        {
            getExtension().setDecomp();
        }
       
        // post decompile status thing.
        configurePostDecomp(getExtension().isDecomp());
    }
   
    /**
     * Allows for the configuration of tasks in AfterEvaluate
     */
    protected void delayedTaskConfig()
    {
        // configure userDev extraction
        // extract userdev
        ((ExtractTask) project.getTasks().findByName("extractUserDev")).from(delayedFile(project.getConfigurations().getByName(CONFIG_USERDEV).getSingleFile().getAbsolutePath()));
        project.getTasks().findByName("getAssetsIndex").dependsOn("extractUserDev");

        // add extraSRG lines to reobf task
        ((ReobfTask) project.getTasks().getByName("reobf")).setExtraSrg(getExtension().getSrgExtra());
       
        // configure output of recompile task
        {
            JavaCompile compile = (JavaCompile) project.getTasks().getByName("recompMinecraft");
            compile.setDestinationDir(delayedFile(RECOMP_CLS_DIR).call());
        }
       
        // configure output of repackage task.
        {
            Jar repackageTask = (Jar) project.getTasks().getByName("repackMinecraft");
            final DelayedFile recomp = delayedDirtyFile(getSrcDepName(), null, "jar");
           
            //done in the delayed configuration.
            File out = recomp.call();
            repackageTask.setArchiveName(out.getName());
            repackageTask.setDestinationDir(out.getParentFile());
        }
       
        // Add the mod and stuff to the classpath of the exec tasks.
        final Jar jarTask = (Jar) project.getTasks().getByName("jar");
       
        JavaExec exec = (JavaExec) project.getTasks().getByName("runClient");
        {
            exec.jvmArgs("-Djava.library.path=" + delayedFile(NATIVES_DIR).call().getAbsolutePath());
            exec.classpath(project.getConfigurations().getByName("runtime"));
            exec.classpath(jarTask.getArchivePath());
            exec.dependsOn(jarTask);
        }
       
        exec = (JavaExec) project.getTasks().getByName("runServer");
        {
            exec.classpath(project.getConfigurations().getByName("runtime"));
            exec.classpath(jarTask.getArchivePath());
            exec.dependsOn(jarTask);
        }
       
        exec = (JavaExec) project.getTasks().getByName("debugClient");
        {
            exec.jvmArgs("-Djava.library.path=" + delayedFile(NATIVES_DIR).call().getAbsolutePath());
            exec.classpath(project.getConfigurations().getByName("runtime"));
            exec.classpath(jarTask.getArchivePath());
            exec.dependsOn(jarTask);
        }
       
        exec = (JavaExec) project.getTasks().getByName("debugServer");
        {
            exec.classpath(project.getConfigurations().getByName("runtime"));
            exec.classpath(jarTask.getArchivePath());
            exec.dependsOn(jarTask);
        }
       
        // configure source replacement.
        for (SourceCopyTask t : project.getTasks().withType(SourceCopyTask.class))
        {
            t.replace(getExtension().getReplacements());
            t.include(getExtension().getIncludes());
        }
    }
   
    /**
     * Configure tasks and stuff after you know if the decomp file exists or not.
     */
    protected void configurePostDecomp(boolean decomp)
    {
        if (decomp)
        {
            ((ReobfTask) project.getTasks().getByName("reobf")).setDeobfFile(((ProcessJarTask) project.getTasks().getByName("deobfuscateJar")).getDelayedOutput());
            ((ReobfTask) project.getTasks().getByName("reobf")).setRecompFile(delayedDirtyFile(getSrcDepName(), null, "jar"));
        }
        else
        {
            (project.getTasks().getByName("compileJava")).dependsOn("deobfBinJar");
            (project.getTasks().getByName("compileApiJava")).dependsOn("deobfBinJar");
        }
       
        setMinecraftDeps(decomp, false);
    }
   
    protected void setMinecraftDeps(boolean decomp, boolean remove)
    {
        String version = getMcVersion(getExtension());
        if (hasApiVersion())
            version = getApiVersion(getExtension());
       
       
        if (decomp)
        {
            project.getDependencies().add(CONFIG_MC, ImmutableMap.of("name", getSrcDepName(), "version", version));
            if (remove)
            {
                project.getConfigurations().getByName(CONFIG_MC).exclude(ImmutableMap.of("module", getBinDepName()));
            }
        }
        else
        {
            project.getDependencies().add(CONFIG_MC, ImmutableMap.of("name", getBinDepName(), "version", version));
            if (remove)
            {
                project.getConfigurations().getByName(CONFIG_MC).exclude(ImmutableMap.of("module", getSrcDepName()));
            }
        }
    }
   
    /**
     * Add Forge/FML ATs here.
     * This happens during normal evaluation, and NOT AfterEvaluate.
     */
    protected abstract void configureDeobfuscation(ProcessJarTask task);
   
    protected abstract void doVersionChecks(String version);
   
    /**
     * Returns a file in the DirtyDir if the deobfusctaion task is dirty. Otherwise returns the cached one.
     * @param classifier
     * @param ext
     * @return
     */
    @SuppressWarnings("serial")
    protected DelayedFile delayedDirtyFile(final String name, final String classifier, final String ext)
    {
        return new DelayedFile(project, "", this) {
            @Override
            public File call()
            {
                ProcessJarTask decompDeobf = (ProcessJarTask) project.getTasks().getByName("deobfuscateJar");
                pattern = (decompDeobf.isClean() ? "{API_CACHE_DIR}" : DIRTY_DIR) + "/";
               
                if (!Strings.isNullOrEmpty(name))
                    pattern += name;
                else
                    pattern += "{API_NAME}";
               
                pattern += "-" + (hasApiVersion() ? "{API_VERSION}" : "{MC_VERSION}");
               
                if (!Strings.isNullOrEmpty(classifier))
                    pattern+= "-"+classifier;
                if (!Strings.isNullOrEmpty(ext))
                    pattern+= "."+ext;
               
                return super.call();
            }
        };
    }
   
    /**
     * This extension object will have the name "minecraft"
     * @return
     */
    @SuppressWarnings("unchecked")
    protected Class<T> getExtensionClass()
    {
        return (Class<T>) UserExtension.class;
    }
}
TOP

Related Classes of net.minecraftforge.gradle.user.UserBasePlugin

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.