Java tutorial
/***************************************************************************\ * 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 { } }