Search in sources :

Example 6 with ASMDataTable

use of net.minecraftforge.fml.common.discovery.ASMDataTable in project Bookshelf by Darkhax-Minecraft.

the class AnnotationUtils method getAnnotations.

/**
     * Finds all classes annotated with the annotation class. These classes are then
     * instantiated, added to a list, and given to you.
     *
     * @param table The ASMDataTable created by Forge. You can get this from most of the main
     *        mod loading stage events.
     * @param annotation The class of the annotation you're using to search for.
     * @param instance The class of the thing you're trying to construct. This should be a
     *        shared interface, or parent class.
     * @return A list of all classes annotated with the annotation, as instances.
     */
public static <T, A extends Annotation> Map<T, A> getAnnotations(ASMDataTable table, Class<A> annotation, Class<T> instance) {
    final Map<T, A> map = new HashMap<>();
    for (final ASMDataTable.ASMData asmData : getData(table, annotation)) {
        try {
            final Class<?> asmClass = Class.forName(asmData.getClassName());
            final Class<? extends T> asmInstanceClass = asmClass.asSubclass(instance);
            map.put(asmInstanceClass.newInstance(), asmInstanceClass.getAnnotation(annotation));
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            Constants.LOG.warn("Could not load " + asmData.getClassName(), e);
        }
    }
    return map;
}
Also used : ASMData(net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData) ASMDataTable(net.minecraftforge.fml.common.discovery.ASMDataTable) HashMap(java.util.HashMap)

Example 7 with ASMDataTable

use of net.minecraftforge.fml.common.discovery.ASMDataTable in project Guide-API by TeamAmeriFrance.

the class AnnotationHandler method registerBooks.

public static void registerBooks(ASMDataTable dataTable) {
    for (ASMDataTable.ASMData data : dataTable.getAll(GuideBook.class.getCanonicalName())) {
        try {
            Class<?> genericClass = Class.forName(data.getClassName());
            if (!IGuideBook.class.isAssignableFrom(genericClass))
                continue;
            IGuideBook guideBook = (IGuideBook) genericClass.newInstance();
            Book book = guideBook.buildBook();
            if (book == null)
                continue;
            APISetter.registerBook(book);
            BOOK_CLASSES.add(Pair.of(book, guideBook));
        } catch (Exception e) {
            LogHelper.error("Error registering book for class " + data.getClassName());
            e.printStackTrace();
        }
    }
    APISetter.setIndexedBooks(Lists.newArrayList(GuideAPI.getBooks().values()));
}
Also used : GuideBook(amerifrance.guideapi.api.GuideBook) IGuideBook(amerifrance.guideapi.api.IGuideBook) ASMDataTable(net.minecraftforge.fml.common.discovery.ASMDataTable) GuideBook(amerifrance.guideapi.api.GuideBook) IGuideBook(amerifrance.guideapi.api.IGuideBook) Book(amerifrance.guideapi.api.impl.Book) IGuideBook(amerifrance.guideapi.api.IGuideBook)

Example 8 with ASMDataTable

use of net.minecraftforge.fml.common.discovery.ASMDataTable in project Charset by CharsetMC.

the class ModuleLoader method readDataTable.

@SuppressWarnings("unchecked")
private void readDataTable(ASMDataTable table) {
    Multimap<String, String> unmetDependencies = HashMultimap.create();
    Set<String> enabledModules = new HashSet<>();
    Set<String> compatModules = new HashSet<>();
    Map<String, ASMDataTable.ASMData> moduleData = new HashMap<>();
    Property baseProfileProp = ModCharset.configGeneral.get("general", "profile", "DEFAULT");
    baseProfileProp.setValidValues(new String[] { "DEFAULT", "STABLE", "TESTING", "EXPERIMENTAL" });
    baseProfileProp.setLanguageKey("config.charset.profile.name");
    baseProfileProp.setRequiresMcRestart(true);
    ModuleProfile profile, defaultProfile;
    if (ModCharset.INDEV) {
        defaultProfile = ModuleProfile.INDEV;
    } else if (ModCharset.defaultOptions.containsKey("profile")) {
        defaultProfile = getProfileFromString(ModCharset.defaultOptions.get("profile"));
    } else {
        defaultProfile = ModuleProfile.STABLE;
    }
    baseProfileProp.setComment("Set the base profile for Charset.\nThis will give you a default set of modules based on stability.\nAllowed values: DEFAULT, STABLE, TESTING, EXPERIMENTAL (DEFAULT means " + defaultProfile.name() + ")\nFor fine-grained configuration, check modules.cfg!");
    if ("DEFAULT".equals(baseProfileProp.getString().toUpperCase())) {
        profile = defaultProfile;
    } else {
        profile = getProfileFromString(baseProfileProp.getString());
    }
    ModCharset.profile = profile;
    ModCharset.logger.info("Charset profile is " + ModCharset.profile);
    ConfigCategory category = ModCharset.configModules.getCategory("overrides");
    category.setComment("Overrides can have one of three values: DEFAULT, ENABLE, DISABLE\nDEFAULT will enable the module based on your profile settings and dependency availability.");
    category = ModCharset.configModules.getCategory("categories");
    category.setComment("This section allows you to disable certain categories of content, based on a tag system.");
    boolean configDirty = false;
    Map<String, Boolean> categoryMap = new HashMap<>();
    // Initialize categories
    for (ASMDataTable.ASMData data : table.getAll(CharsetModule.class.getName())) {
        Map<String, Object> info = data.getAnnotationInfo();
        List<String> tags = (List<String>) info.getOrDefault("categories", Collections.emptyList());
        for (String s : tags) {
            if (!categoryMap.containsKey(s)) {
                Property prop = ModCharset.configModules.get("categories", s, !CATEGORIES_OFF_BY_DEFAULT.contains(s));
                prop.setRequiresMcRestart(true);
                categoryMap.put(s, prop.getBoolean());
            }
        }
    }
    for (ASMDataTable.ASMData data : table.getAll(CharsetModule.class.getName())) {
        Map<String, Object> info = data.getAnnotationInfo();
        String name = (String) info.get("name");
        String desc = (String) info.get("description");
        if (desc == null)
            desc = "";
        ModuleProfile modProfile = ModuleProfile.valueOf(((ModAnnotation.EnumHolder) info.get("profile")).getValue());
        Boolean isDefault = (Boolean) info.getOrDefault("isDefault", true);
        Boolean compat = modProfile == ModuleProfile.COMPAT;
        Boolean clientOnly = (Boolean) info.getOrDefault("isClientOnly", false);
        Boolean serverOnly = (Boolean) info.getOrDefault("isServerOnly", false);
        List<String> tags = (List<String>) info.getOrDefault("categories", Collections.emptyList());
        String moduleGuiClass = (String) info.getOrDefault("moduleConfigGui", "");
        if (moduleGuiClass.length() > 0) {
            moduleGuiClasses.put(name, moduleGuiClass);
        }
        moduleData.put(name, data);
        ThreeState override = ThreeState.MAYBE;
        if ((Boolean) info.getOrDefault("isVisible", true)) {
            if (modProfile == ModuleProfile.INDEV && profile != ModuleProfile.INDEV) {
                override = ThreeState.NO;
            } else {
                if (compat) {
                    Property prop = ModCharset.configModules.get("compat", name, isDefault);
                    prop.setRequiresMcRestart(true);
                    if (!prop.getBoolean())
                        override = ThreeState.NO;
                } else {
                    Property prop = ModCharset.configModules.get("overrides", name, "DEFAULT");
                    prop.setValidValues(new String[] { "DEFAULT", "ENABLE", "DISABLE" });
                    prop.setRequiresMcRestart(true);
                    if (desc.length() > 0)
                        desc += " ";
                    desc += "[Profile: " + modProfile.name().toUpperCase() + "";
                    if (!isDefault) {
                        desc += ", off by default!";
                    }
                    desc += "]";
                    if (!desc.equals(prop.getComment())) {
                        prop.setComment(desc);
                        configDirty = true;
                    }
                    if (prop.getString().toUpperCase().startsWith("ENABLE")) {
                        override = ThreeState.YES;
                    } else if (prop.getString().toUpperCase().startsWith("DISABLE")) {
                        override = ThreeState.NO;
                    } else if (!"DEFAULT".equals(prop.getString().toUpperCase())) {
                        ModCharset.logger.warn("Invalid value for '" + name + "' override: '" + prop.getString() + ";");
                    }
                }
            }
        }
        if (clientOnly && !FMLCommonHandler.instance().getSide().isClient()) {
            continue;
        }
        if (serverOnly && !FMLCommonHandler.instance().getSide().isServer()) {
            continue;
        }
        if (compat) {
            compatModules.add(name);
        }
        if (override == ThreeState.MAYBE && isDefault) {
            List<String> antideps = (List<String>) info.get("antidependencies");
            if (antideps != null) {
                for (String dep : antideps) {
                    if (isDepPresent(dep, enabledModules)) {
                        ModCharset.logger.info("Antidependency " + dep + " is present - disabling otherwise not forced module " + name + ".");
                        isDefault = false;
                        break;
                    }
                }
            }
            for (String s : tags) {
                if (!categoryMap.get(s)) {
                    ModCharset.logger.info("Category " + s + " is disabled - disabling otherwise not forced module " + name + ".");
                    isDefault = false;
                }
            }
        }
        if (!compat && modProfile != ModuleProfile.FORCED && modProfile.ordinal() > profile.ordinal()) {
            isDefault = false;
        }
        EnableInformation enableInfo = new EnableInformation(isDefault, override);
        if (enableInfo.isEnabled()) {
            enabledModules.add(name);
            enableInfoMap.put(name, enableInfo);
            if (!"lib".equals(name))
                dependencies.put(name, "lib");
            List<String> deps = (List<String>) info.get("dependencies");
            if (deps != null) {
                dependencies.putAll(name, deps);
            }
        }
    }
    if (ModCharset.configGeneral.hasChanged()) {
        ModCharset.configGeneral.save();
    }
    if (ModCharset.configModules.hasChanged() || configDirty) {
        ModCharset.configModules.save();
        configDirty = false;
    }
    int removedCount = 1;
    while (removedCount > 0) {
        removedCount = 0;
        for (String name : enabledModules) {
            if (dependencies.containsKey(name)) {
                for (String dep : dependencies.get(name)) {
                    boolean optional = false;
                    if (dep.startsWith("optional:")) {
                        optional = true;
                        dep = dep.substring("optional:".length());
                    }
                    boolean met = optional || isDepPresent(dep, enabledModules);
                    if (!met) {
                        enableInfoMap.get(name).dependenciesMet = false;
                        unmetDependencies.put(name, dep);
                        break;
                    }
                }
            }
        }
        Iterator<String> unmetDepKey = unmetDependencies.keySet().iterator();
        while (unmetDepKey.hasNext()) {
            String depMod = unmetDepKey.next();
            EnableInformation enableInfo = enableInfoMap.get(depMod);
            if (!enableInfo.isEnabled()) {
                if (!compatModules.contains(depMod)) {
                    ModCharset.logger.info("Module " + depMod + " requires " + joinerComma.join(unmetDependencies.get(depMod)) + ", but is not force-enabled. You can ignore this - it is not an error, just information.");
                }
                removedCount++;
                enabledModules.remove(depMod);
                unmetDepKey.remove();
            }
        }
    }
    for (String name : enabledModules) {
        if (ModCharset.INDEV) {
            ModCharset.logger.info("Instantiating module " + name);
        }
        ASMDataTable.ASMData data = moduleData.get(name);
        try {
            Object o = getClass(data).newInstance();
            loadedModules.put(name, o);
            loadedModulesByClass.put(data.getClassName(), o);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    if (unmetDependencies.size() > 0) {
        List<String> depStrings = new ArrayList<>(unmetDependencies.size());
        for (String depMod : unmetDependencies.keys()) {
            depStrings.add(depMod + "<-[" + joinerComma.join(unmetDependencies.get(depMod)) + "]");
        }
        throw new RuntimeException("The following mandatory dependencies were not met: " + joinerComma.join(depStrings));
    }
    iterateModules(table, Mod.EventHandler.class.getName(), (data, instance) -> {
        String methodName = data.getObjectName().substring(0, data.getObjectName().indexOf('('));
        String methodDesc = data.getObjectName().substring(methodName.length());
        MethodType methodType = MethodType.fromMethodDescriptorString(methodDesc, classLoader);
        if (ModCharset.INDEV) {
            if (methodType.parameterCount() != 1) {
                throw new RuntimeException("Invalid parameter count " + methodType.parameterCount() + " for EventHandler in " + instance.getClass() + "!");
            }
        }
        try {
            MethodHandle methodHandle = MethodHandles.lookup().findVirtual(getClass(data), methodName, methodType);
            List<Pair<String, MethodHandle>> list = loaderHandles.computeIfAbsent(methodType.parameterType(0), k -> new ArrayList<>());
            list.sort(Comparator.comparing(Pair::getLeft));
            list.add(Pair.of(loadedModules.inverse().get(instance), methodHandle));
        } catch (NoSuchMethodException e) {
        // method has been annotated away, ignore
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    });
    iterateModules(table, CharsetModule.Instance.class.getName(), (data, instance) -> {
        try {
            String instString = (String) data.getAnnotationInfo().get("value");
            if (instString == null || instString.equals("")) {
                getField(data).set(instance, instance);
            } else {
                Object inst2 = loadedModules.get(instString);
                getField(data).set(instance, inst2);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    });
    iterateModules(table, CharsetModule.PacketRegistry.class.getName(), (data, instance) -> {
        String id = (String) data.getAnnotationInfo().get("value");
        if (id == null)
            id = loadedModules.inverse().get(instance);
        try {
            String channelName = "chrs:" + id.substring(id.lastIndexOf('.') + 1);
            getField(data).set(instance, new PacketRegistry(channelName));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    });
    iterateModules(table, CharsetModule.Configuration.class.getName(), (data, instance) -> {
        String id = (String) data.getAnnotationInfo().get("value");
        if (id == null)
            id = loadedModules.inverse().get(instance);
        try {
            Configuration config = new Configuration(ModCharset.getModuleConfigFile(id));
            getField(data).set(instance, config);
            moduleConfigs.put(id, config);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    });
    Side side = FMLCommonHandler.instance().getSide();
    for (ASMDataTable.ASMData data : table.getAll(CharsetModule.SidedProxy.class.getName())) {
        String clientSide = (String) data.getAnnotationInfo().get("clientSide");
        String serverSide = (String) data.getAnnotationInfo().get("serverSide");
        try {
            Field f = getField(data);
            f.set(null, Class.forName(side == Side.CLIENT ? clientSide : serverSide).newInstance());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    List<String> sortedModules = new ArrayList<>();
    Set<String> remainingModules = Sets.newHashSet(enabledModules);
    while (!remainingModules.isEmpty()) {
        Iterator<String> remainingIterator = remainingModules.iterator();
        boolean added = false;
        while (remainingIterator.hasNext()) {
            String s = remainingIterator.next();
            boolean canAdd = true;
            for (String dep : dependencies.get(s)) {
                if (!dep.startsWith("mod:") && !dep.startsWith("optional:") && !sortedModules.contains(dep)) {
                    canAdd = false;
                    break;
                }
            }
            if (canAdd) {
                added = true;
                sortedModules.add(s);
                remainingIterator.remove();
            }
        }
        if (!added) {
            throw new RuntimeException("Cyclic dependency within Charset modules! Report!");
        }
    }
    for (List<Pair<String, MethodHandle>> list : loaderHandles.values()) {
        list.sort(Comparator.comparingInt(a -> sortedModules.indexOf(a.getKey())));
    }
    for (String s : sortedModules) {
        MinecraftForge.EVENT_BUS.register(loadedModules.get(s));
    }
    for (ASMDataTable.ASMData data : table.getAll(CharsetCompatAnnotation.class.getName())) {
        String id = (String) data.getAnnotationInfo().get("value");
        try {
            addClassNames(table, Class.forName(data.getClassName()), id);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    passEvent(new CharsetLoadConfigEvent(true));
    if (ModCharset.configModules.hasChanged() || configDirty) {
        ModCharset.configModules.save();
        configDirty = false;
    }
}
Also used : CharsetMCMPAddon(pl.asie.charset.lib.modcompat.mcmultipart.CharsetMCMPAddon) MethodHandle(java.lang.invoke.MethodHandle) java.util(java.util) Loader(net.minecraftforge.fml.common.Loader) ModCharset(pl.asie.charset.ModCharset) CharsetChiselsAndBitsPlugin(pl.asie.charset.lib.modcompat.chiselsandbits.CharsetChiselsAndBitsPlugin) FMLCommonHandler(net.minecraftforge.fml.common.FMLCommonHandler) ASMDataTable(net.minecraftforge.fml.common.discovery.ASMDataTable) Pair(org.apache.commons.lang3.tuple.Pair) Side(net.minecraftforge.fml.relauncher.Side) BiConsumer(java.util.function.BiConsumer) CharsetJEIPlugin(pl.asie.charset.lib.modcompat.jei.CharsetJEIPlugin) Mod(net.minecraftforge.fml.common.Mod) com.google.common.collect(com.google.common.collect) FMLEvent(net.minecraftforge.fml.common.event.FMLEvent) PacketRegistry(pl.asie.charset.lib.network.PacketRegistry) ThreeState(pl.asie.charset.lib.utils.ThreeState) CharsetLoadConfigEvent(pl.asie.charset.lib.config.CharsetLoadConfigEvent) MethodHandles(java.lang.invoke.MethodHandles) Field(java.lang.reflect.Field) ModAnnotation(net.minecraftforge.fml.common.discovery.asm.ModAnnotation) MinecraftForge(net.minecraftforge.common.MinecraftForge) MethodType(java.lang.invoke.MethodType) Configuration(net.minecraftforge.common.config.Configuration) Property(net.minecraftforge.common.config.Property) ConfigCategory(net.minecraftforge.common.config.ConfigCategory) Joiner(com.google.common.base.Joiner) Configuration(net.minecraftforge.common.config.Configuration) Side(net.minecraftforge.fml.relauncher.Side) ThreeState(pl.asie.charset.lib.utils.ThreeState) Field(java.lang.reflect.Field) ASMDataTable(net.minecraftforge.fml.common.discovery.ASMDataTable) ConfigCategory(net.minecraftforge.common.config.ConfigCategory) ModAnnotation(net.minecraftforge.fml.common.discovery.asm.ModAnnotation) Property(net.minecraftforge.common.config.Property) Pair(org.apache.commons.lang3.tuple.Pair) MethodType(java.lang.invoke.MethodType) PacketRegistry(pl.asie.charset.lib.network.PacketRegistry) CharsetLoadConfigEvent(pl.asie.charset.lib.config.CharsetLoadConfigEvent) MethodHandle(java.lang.invoke.MethodHandle)

Example 9 with ASMDataTable

use of net.minecraftforge.fml.common.discovery.ASMDataTable in project Charset by CharsetMC.

the class ModuleLoader method addClassNames.

private void addClassNames(ASMDataTable table, Class annotationClass, String confType) {
    for (ASMDataTable.ASMData data : table.getAll(annotationClass.getName())) {
        String id = (String) data.getAnnotationInfo().get("value");
        Property prop = ModCharset.configModules.get("compat", confType + ":" + id, true);
        boolean enabled = prop.getBoolean();
        if (enabled && loadedModules.containsKey(id)) {
            classNames.put(annotationClass, data.getClassName());
        }
    }
}
Also used : ASMDataTable(net.minecraftforge.fml.common.discovery.ASMDataTable) Property(net.minecraftforge.common.config.Property)

Example 10 with ASMDataTable

use of net.minecraftforge.fml.common.discovery.ASMDataTable in project ClaySoldiersMod by SanAndreasP.

the class ClaySoldiersMod method loadPlugins.

private static void loadPlugins(ASMDataTable dataTable) {
    String annotationClassName = CsmPlugin.class.getCanonicalName();
    Set<ASMDataTable.ASMData> asmDatas = dataTable.getAll(annotationClassName);
    for (ASMDataTable.ASMData asmData : asmDatas) {
        try {
            Class<?> asmClass = Class.forName(asmData.getClassName());
            Class<? extends ICsmPlugin> asmInstanceClass = asmClass.asSubclass(ICsmPlugin.class);
            ICsmPlugin instance = asmInstanceClass.getConstructor().newInstance();
            PLUGINS.add(instance);
        } catch (ClassNotFoundException | IllegalAccessException | ExceptionInInitializerError | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
            CsmConstants.LOG.log(Level.ERROR, "Failed to load: {}", asmData.getClassName(), e);
        }
    }
}
Also used : InvocationTargetException(java.lang.reflect.InvocationTargetException) ICsmPlugin(de.sanandrew.mods.claysoldiers.api.ICsmPlugin) ASMDataTable(net.minecraftforge.fml.common.discovery.ASMDataTable)

Aggregations

ASMDataTable (net.minecraftforge.fml.common.discovery.ASMDataTable)15 Field (java.lang.reflect.Field)4 ASMData (net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData)4 Stopwatch (com.google.common.base.Stopwatch)3 ArrayList (java.util.ArrayList)3 List (java.util.List)3 ResourceLocation (net.minecraft.util.ResourceLocation)3 Nonnull (javax.annotation.Nonnull)2 Property (net.minecraftforge.common.config.Property)2 ModAnnotation (net.minecraftforge.fml.common.discovery.asm.ModAnnotation)2 Side (net.minecraftforge.fml.relauncher.Side)2 Pair (org.apache.commons.lang3.tuple.Pair)2 BloodMagicPlugin (WayofTime.bloodmagic.api.BloodMagicPlugin)1 IBloodMagicPlugin (WayofTime.bloodmagic.api.IBloodMagicPlugin)1 GuideBook (amerifrance.guideapi.api.GuideBook)1 IGuideBook (amerifrance.guideapi.api.IGuideBook)1 Book (amerifrance.guideapi.api.impl.Book)1 INBTData (arekkuusu.solar.api.entanglement.quantum.data.INBTData)1 NBTHolder (arekkuusu.solar.api.entanglement.quantum.data.INBTData.NBTHolder)1 Joiner (com.google.common.base.Joiner)1