net.minecraftforge.gradle.common.BaseExtension.java Source code

Java tutorial

Introduction

Here is the source code for net.minecraftforge.gradle.common.BaseExtension.java

Source

/*
 * 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.common;

import java.net.URL;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;

import org.gradle.api.Project;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Resources;

import net.minecraftforge.gradle.util.GradleConfigurationException;
import net.minecraftforge.gradle.util.delayed.ReplacementProvider;

public abstract class BaseExtension {
    protected static final transient Map<String, String> MCP_VERSION_MAP = ImmutableMap.of("1.8", "9.10");

    public final String forgeGradleVersion;

    protected transient Project project;
    protected transient ReplacementProvider replacer;
    protected String version;
    protected String mcpVersion = "unknown";

    // this should never be touched except by the base plugin in this package
    Map<String, Map<String, int[]>> mcpJson;
    protected boolean mappingsSet = false;
    protected String mappingsChannel = null;
    protected int mappingsVersion = -1;
    // custom version for custom mappings
    protected String mappingsCustom = null;

    public BaseExtension(BasePlugin<? extends BaseExtension> plugin) {
        this.project = plugin.project;
        this.replacer = plugin.replacer;

        String version;
        try {
            URL url = BaseExtension.class.getClassLoader().getResource("forgegradle.version.txt");
            version = Resources.toString(url, Constants.CHARSET).trim();

            if (version.equals("${version}")) {
                version = "2.0-SNAPSHOT";// fallback
            }

        } catch (Exception e) {
            // again, the fallback
            version = "2.0-SNAPSHOT";
        }

        forgeGradleVersion = version;
    }

    /**
     * Get the Minecraft version
     *
     * @return The Minecraft version
     */
    public String getVersion() {
        return version;
    }

    /**
     * Set the Minecraft version
     *
     * @param version The Minecraft version
     */
    public void setVersion(String version) {
        this.version = version;

        replacer.putReplacement(Constants.REPLACE_MC_VERSION, version);

        mcpVersion = MCP_VERSION_MAP.get(version);

        // maybe they set the mappings first
        checkMappings();
    }

    /**
     * Get the MCP data version
     *
     * @return The MCP data version
     */
    public String getMcpVersion() {
        return mcpVersion == null ? "unknown" : mcpVersion;
    }

    public void setMcpVersion(String mcpVersion) {
        this.mcpVersion = mcpVersion;
    }

    public void copyFrom(BaseExtension ext) {
        if ("null".equals(version)) {
            setVersion(ext.getVersion());
        }

        if ("unknown".equals(mcpVersion)) {
            setMcpVersion(ext.getMcpVersion());
        }
    }

    /**
     * Get the MCP mappings channel and version<br>
     * Examples: {@code stable_17, snapshot_20151113}
     *
     * @return The channel and version in format: {@code channel_version}.
     *
     * @see <a href="http://export.mcpbot.bspk.rs/">http://export.mcpbot.bspk.rs/</a>
     */
    public String getMappings() {
        return mappingsChannel + "_" + (mappingsCustom == null ? mappingsVersion : mappingsCustom);
    }

    /**
     * Get the MCP mappings channel
     *
     * @return The channel
     *
     * @see <a href="http://export.mcpbot.bspk.rs/">http://export.mcpbot.bspk.rs/</a>
     */
    public String getMappingsChannel() {
        return mappingsChannel;
    }

    /**
     * Strips the _nodoc and _verbose channel subtypes from the channel name.
     *
     * @return The channel without subtype
     */
    public String getMappingsChannelNoSubtype() {
        int underscore = mappingsChannel.indexOf('_');
        if (underscore <= 0) // already has docs.
            return mappingsChannel;
        else
            return mappingsChannel.substring(0, underscore);
    }

    /**
     * Get the MCP mappings version
     *
     * @return The version
     *
     * @see <a href="http://export.mcpbot.bspk.rs/">http://export.mcpbot.bspk.rs/</a>
     */
    public String getMappingsVersion() {
        return mappingsCustom == null ? "" + mappingsVersion : mappingsCustom;
    }

    /**
     * Set the MCP mappings channel and version<br>
     * The format is: {@code channel_version}.<br>
     * Examples: {@code stable_17, snapshot_20151113}
     *
     * @param mappings The channel and version
     *
     * @see <a href="http://export.mcpbot.bspk.rs/">http://export.mcpbot.bspk.rs/</a>
     */
    public void setMappings(String mappings) {
        if (Strings.isNullOrEmpty(mappings)) {
            mappingsChannel = null;
            mappingsVersion = -1;

            replacer.putReplacement(Constants.REPLACE_MCP_CHANNEL, mappingsChannel);
            replacer.putReplacement(Constants.REPLACE_MCP_VERSION, getMappingsVersion());

            return;
        }

        mappings = mappings.toLowerCase();

        if (!mappings.contains("_")) {
            throw new IllegalArgumentException(
                    "Mappings must be in format 'channel_version' or 'custom_something'. eg: snapshot_20140910 custom_AbrarIsCool");
        }

        int index = mappings.lastIndexOf('_');
        mappingsChannel = mappings.substring(0, index);
        mappingsCustom = mappings.substring(index + 1);

        if (!mappingsCustom.equals("custom")) {
            try {
                mappingsVersion = Integer.parseInt(mappingsCustom);
                mappingsCustom = null;
            } catch (NumberFormatException e) {
                throw new GradleConfigurationException(
                        "The mappings version must be a number! eg: channel_### or channel_custom (for custom mappings).");
            }
        }

        mappingsSet = true;

        replacer.putReplacement(Constants.REPLACE_MCP_CHANNEL, mappingsChannel);
        replacer.putReplacement(Constants.REPLACE_MCP_VERSION, getMappingsVersion());

        // check
        checkMappings();
    }

    /**
     * Checks that the set mappings are valid based on the channel, version, and MC version.
     * If the mappings are invalid, this method will throw a runtime exception.
     */
    protected void checkMappings() {
        // mappings or mc version are null
        if (mappingsChannel == null || Strings.isNullOrEmpty(version) || mappingsCustom != null)
            return;

        // check if it exists
        Map<String, int[]> versionMap = mcpJson.get(version);
        if (versionMap == null)
            throw new GradleConfigurationException("There are no mappings for MC " + version);

        String channel = getMappingsChannelNoSubtype();
        int[] channelList = versionMap.get(channel);
        if (channelList == null)
            throw new GradleConfigurationException("There is no such MCP mapping channel named " + channel);

        // all is well with the world
        if (searchArray(channelList, mappingsVersion))
            return;

        // if it gets here.. it wasnt found. Now we try to actually find it..
        for (Entry<String, Map<String, int[]>> mcEntry : mcpJson.entrySet()) {
            for (Entry<String, int[]> channelEntry : mcEntry.getValue().entrySet()) {
                // found it!
                if (searchArray(channelEntry.getValue(), mappingsVersion)) {
                    boolean rightMc = mcEntry.getKey().equals(version);
                    boolean rightChannel = channelEntry.getKey().equals(channel);

                    // right channel, but wrong mc
                    if (rightChannel && !rightMc) {
                        throw new GradleConfigurationException("This mapping '" + getMappings()
                                + "' exists only for MC " + mcEntry.getKey() + "!");
                    }

                    // right MC , but wrong channel
                    else if (rightMc && !rightChannel) {
                        throw new GradleConfigurationException(
                                "This mapping '" + getMappings() + "' doesnt exist! perhaps you meant '"
                                        + channelEntry.getKey() + "_" + mappingsVersion + "'");
                    }
                }
            }
        }

        // wasnt found
        throw new GradleConfigurationException("The specified mapping '" + getMappings() + "' does not exist!");
    }

    private static boolean searchArray(int[] array, int key) {
        Arrays.sort(array);
        int foundIndex = Arrays.binarySearch(array, key);
        return foundIndex >= 0 && array[foundIndex] == key;
    }
}