net.lyonlancer5.mcmp.unmapi.xejon.XejonLoader.java Source code

Java tutorial

Introduction

Here is the source code for net.lyonlancer5.mcmp.unmapi.xejon.XejonLoader.java

Source

/***************************************************************************\
* Copyright 2017 [Lyonlancer5]                                              *
*                                                                           *
* Licensed under the Apache License, Version 2.0 (the "License");           *
* you may not use this file except in compliance with the License.          *
* You may obtain a copy of the License at                                   *
*                                                                           *
*     http://www.apache.org/licenses/LICENSE-2.0                            *
*                                                                           *
* Unless required by applicable law or agreed to in writing, software       *
* distributed under the License is distributed on an "AS IS" BASIS,         *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
* See the License for the specific language governing permissions and       *
* limitations under the License.                                            *
\***************************************************************************/
package net.lyonlancer5.mcmp.unmapi.xejon;

import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;

import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.common.FMLModContainer;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.MetadataCollection;
import cpw.mods.fml.common.discovery.ContainerType;
import cpw.mods.fml.common.discovery.ModCandidate;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.LanguageRegistry;
import net.lyonlancer5.mcmp.unmapi.Constants;
import net.lyonlancer5.mcmp.unmapi.lib.collect.WeakPair;
import net.lyonlancer5.mcmp.unmapi.util.io.FSTools;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;

/**
 * Loader for JSON-based mods.
 * @author Lyonlancer5
 */
public class XejonLoader {

    private static final Logger LOGGER = LogManager.getLogger("LMLAPI - Xejon Extensions");
    //private static final Pattern ZIPJAR = Pattern.compile("(.+).(zip|jar)$");
    private static final Pattern TXT_JSON = Pattern.compile("(.+).(txt|json)$");

    private final List<Pair<String, Pair<File, JsonElement>>> jsonPackIds = Lists.newArrayList();

    private ClassLoader theClassLoader;
    private Method mURLClassLoader_addURL;

    /**No exceptions are to be generated, fail gracefully if false*/
    private volatile boolean success;

    /**
     * Constructor for the loader
     */
    //@NonApi({"net.lyonlancer5.mcmp.unmapi.LL5_Unmapi"})
    public XejonLoader() {
        //NonApi.Impl.checkAccess(ReflectionUtils.getCaller());

        theClassLoader = Thread.currentThread().getContextClassLoader();
        try {
            mURLClassLoader_addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
            mURLClassLoader_addURL.setAccessible(true);
            success = mURLClassLoader_addURL.isAccessible();
            LOGGER.info("Xejon Loader initialized");
        } catch (Exception e) {
            LOGGER.error("URLClassLoader#addURL method reflection failed", e);
            success = false;
        }
    }

    /**
     * Enumerates the extensions present and checks for dupes
     */
    public void enumerate() {
        if (success) {
            LOGGER.info("Enumerating sources from " + Constants.EXTENSIONS_DIR.getAbsolutePath());

            List<String> registeredID = Lists.newArrayList();
            for (File directory : Constants.EXTENSIONS_DIR.listFiles(new FileFilter() {
                public boolean accept(File pathname) {
                    return pathname.isDirectory();
                }
            })) {

                LOGGER.trace("Looking in " + directory.getPath());

                List<File> jsonFilesInDir = FSTools.findRecursively(directory, TXT_JSON);

                for (File jsonFile : jsonFilesInDir) {
                    if (jsonFile.getName().endsWith("pack-info.json")
                            || jsonFile.getName().endsWith("pack-info.txt")) {
                        LOGGER.debug("Found JSON pack info in " + directory.getPath());

                        try {
                            JsonParser parser = new JsonParser();
                            JsonObject rootObject = parser.parse(new FileReader(jsonFile)).getAsJsonObject();
                            String str = rootObject.get("id").getAsString();
                            if (!(str.equals("null") && registeredID.contains(str))) {
                                registeredID.add(str);
                                jsonPackIds.add(Pair.of(str, Pair.of(jsonFile.getParentFile(), rootObject)));
                                LOGGER.debug("Registered an extension pack with ID: " + str);
                            }
                        } catch (IOException | JsonParseException e) {
                            LOGGER.warn("Cannot read pack-info.json in " + jsonFile.getParent() + ", ignoring");
                        }
                    }
                }

                LOGGER.info("Read through " + jsonPackIds.size() + " candidate directories");
            }
        } else {
            LOGGER.warn("Reflection failed, all extensions will fail to load!");
            jsonPackIds.clear();
        }
    }

    public void load() {
        for (Pair<String, Pair<File, JsonElement>> jsonPack : jsonPackIds) {
            LOGGER.info("Loading JSON pack: " + jsonPack.getKey());
            try {
                mURLClassLoader_addURL.invoke(theClassLoader, jsonPack.getValue().getKey().toURI().toURL());
                LOGGER.trace("Added pack folder into URL class loader");
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
                    | MalformedURLException e) {
                LOGGER.warn("Cannot load JSON pack into JVM: " + jsonPack.getKey(), e);
                continue;
            }

            Map<String, Object> jsonModInfo = Maps.newHashMap();

            try {
                JsonObject rootObject = jsonPack.getValue().getRight().getAsJsonObject();
                String str = rootObject.get("id").getAsString();
                if (!str.equals("null")) {
                    jsonModInfo.put("modid", str);
                    jsonModInfo.put("name", rootObject.get("name").getAsString());
                    jsonModInfo.put("version", rootObject.get("version").getAsString());
                } else if (Loader.isModLoaded(str)) {
                    LOGGER.error("A JSON pack has an ID conflict with another mod!");
                    LOGGER.error("If you wish to force an override in here, specify");
                    LOGGER.error("conflictOverride:true in the JSON pack info");
                    continue;
                }
                //} catch (IOException e) {
                //   LOGGER.warn("A JSON pack info was found and registered but is now unreadable!", e);
                //   continue;
            } catch (JsonParseException e) {
                LOGGER.warn("Syntax errors were found on the JSON file " + jsonPack.getValue().getKey().getName(),
                        e);
                continue;
            }

            List<File> packContents = FSTools.findRecursively(jsonPack.getValue().getKey().getParentFile(),
                    TXT_JSON);
            for (File jsonFileToParse : packContents) {

                try {
                    LOGGER.debug("Parsing file " + jsonFileToParse.getName());
                    final JsonParser theParser = new JsonParser();
                    JsonObject root = theParser.parse(new FileReader(jsonFileToParse)).getAsJsonObject();

                    String itemType = root.get("type").getAsString();
                    JsonObject data = root.get("data").getAsJsonObject();
                    if (data != null) {

                        String id = data.get("id").getAsString();
                        int stack_size = data.get("stack_size").getAsInt();
                        String icon = data.get("icons").getAsJsonObject().get("itemIcon").getAsString();

                        JsonArray raw = data.get("names").getAsJsonArray();
                        List<Pair<String, String>> langCodes = Lists.newArrayList();
                        for (JsonElement e : raw) {
                            String s0 = e.getAsString();
                            String[] s1 = s0.split("=", 2);
                            langCodes.add(WeakPair.of(s1[0], s1[1]));
                        }

                        switch (itemType) {
                        case "armor":

                            break;
                        case "tool":

                            break;
                        case "item":

                            Item item = new Item() {

                                public Item setMaxStackSize(int p_77625_1_) {
                                    this.maxStackSize = stack_size;
                                    return this;
                                }

                                public String getUnlocalizedName() {
                                    return "item." + jsonModInfo.get("modid") + "." + id;
                                }

                                public String getUnlocalizedName(ItemStack p_77667_1_) {
                                    return getUnlocalizedName();
                                }

                                public void registerIcons(IIconRegister p_94581_1_) {
                                    this.itemIcon = p_94581_1_.registerIcon(icon);
                                }

                            };

                            GameRegistry.registerItem(item, item.getUnlocalizedName().substring(5));
                            for (Pair<String, String> pair : langCodes) {
                                LanguageRegistry.instance().addStringLocalization(
                                        item.getUnlocalizedName() + ".name", pair.getKey(), pair.getValue());
                            }
                            break;
                        default:
                            LOGGER.warn("Illegal item type at " + jsonFileToParse.getName());
                        }
                    }

                } catch (IOException | JsonParseException | ClassCastException e) {
                    LOGGER.warn("Exception caught while parsing file: " + jsonFileToParse.getName(), e);
                }
            }

            FMLModContainer container = new FMLModContainer(XejonLoader.JsonModDelegate.class.getName(),
                    new ModCandidate(jsonPack.getRight().getKey(), jsonPack.getValue().getLeft(),
                            ContainerType.DIR),
                    jsonModInfo);
            container.bindMetadata(MetadataCollection.from(null, ""));
            FMLClientHandler.instance().addModAsResource(container);
            LOGGER.info("Parser is a work-in-progress. Features may not work as intended if any are loaded.");

        }
    }

    public static class JsonModDelegate {
    }

}