private void parseSimpleFieldAnnotation( SetMultimap<String, ASMData> annotations, String annotationClassName, Function<ModContainer, Object> retreiver) throws IllegalAccessException { String[] annName = annotationClassName.split("\\."); String annotationName = annName[annName.length - 1]; for (ASMData targets : annotations.get(annotationClassName)) { String targetMod = (String) targets.getAnnotationInfo().get("value"); Field f = null; Object injectedMod = null; ModContainer mc = this; boolean isStatic = false; Class<?> clz = modInstance.getClass(); if (!Strings.isNullOrEmpty(targetMod)) { if (Loader.isModLoaded(targetMod)) { mc = Loader.instance().getIndexedModList().get(targetMod); } else { mc = null; } } if (mc != null) { try { clz = Class.forName(targets.getClassName(), true, Loader.instance().getModClassLoader()); f = clz.getDeclaredField(targets.getObjectName()); f.setAccessible(true); isStatic = Modifier.isStatic(f.getModifiers()); injectedMod = retreiver.apply(mc); } catch (Exception e) { Throwables.propagateIfPossible(e); FMLLog.log( getModId(), Level.WARNING, e, "Attempting to load @%s in class %s for %s and failing", annotationName, targets.getClassName(), mc.getModId()); } } if (f != null) { Object target = null; if (!isStatic) { target = modInstance; if (!modInstance.getClass().equals(clz)) { FMLLog.log( getModId(), Level.WARNING, "Unable to inject @%s in non-static field %s.%s for %s as it is NOT the primary mod instance", annotationName, targets.getClassName(), targets.getObjectName(), mc.getModId()); continue; } } f.set(target, injectedMod); } } }
public void transition(LoaderState desiredState) { LoaderState oldState = state; state = state.transition(!errors.isEmpty()); if (state != desiredState) { Throwable toThrow = null; FMLLog.severe( "Fatal errors were detected during the transition from %s to %s. Loading cannot continue", oldState, desiredState); StringBuilder sb = new StringBuilder(); printModStates(sb); FMLLog.getLogger().severe(sb.toString()); if (errors.size() > 0) { FMLLog.severe("The following problems were captured during this phase"); for (Entry<String, Throwable> error : errors.entries()) { FMLLog.log(Level.SEVERE, error.getValue(), "Caught exception from %s", error.getKey()); if (error.getValue() instanceof IFMLHandledException) { toThrow = error.getValue(); } else if (toThrow == null) { toThrow = error.getValue(); } } } else { FMLLog.severe( "The ForgeModLoader state engine has become corrupted. Probably, a state was missed by and invalid modification to a base class" + "ForgeModLoader depends on. This is a critical error and not recoverable. Investigate any modifications to base classes outside of" + "ForgeModLoader, especially Optifine, to see if there are fixes available."); throw new RuntimeException("The ForgeModLoader state engine is invalid"); } if (toThrow != null && toThrow instanceof RuntimeException) { throw (RuntimeException) toThrow; } else { throw new LoaderException(toThrow); } } }
public void runtimeDisableMod(String modId) { ModContainer mc = namedMods.get(modId); Disableable disableable = mc.canBeDisabled(); if (disableable == Disableable.NEVER) { FMLLog.info("Cannot disable mod %s - it is never allowed to be disabled", modId); return; } if (disableable == Disableable.DEPENDENCIES) { FMLLog.info( "Cannot disable mod %s - there are dependent mods that require its presence", modId); return; } if (disableable == Disableable.YES) { FMLLog.info("Runtime disabling mod %s", modId); modController.disableMod(mc); List<ModContainer> localmods = Lists.newArrayList(mods); localmods.remove(mc); mods = ImmutableList.copyOf(localmods); } try { Properties props = new Properties(); props.load(new FileReader(forcedModFile)); props.put(modId, "false"); props.store(new FileWriter(forcedModFile), null); } catch (Exception e) { FMLLog.log( Level.INFO, e, "An error occurred writing the fml mod states file, your disabled change won't persist"); } }
public Properties searchForVersionProperties() { try { FMLLog.log( getModId(), Level.FINE, "Attempting to load the file version.properties from %s to locate a version number for %s", getSource().getName(), getModId()); Properties version = null; if (getSource().isFile()) { ZipFile source = new ZipFile(getSource()); ZipEntry versionFile = source.getEntry("version.properties"); if (versionFile != null) { version = new Properties(); version.load(source.getInputStream(versionFile)); } source.close(); } else if (getSource().isDirectory()) { File propsFile = new File(getSource(), "version.properties"); if (propsFile.exists() && propsFile.isFile()) { version = new Properties(); FileInputStream fis = new FileInputStream(propsFile); version.load(fis); fis.close(); } } return version; } catch (Exception e) { Throwables.propagateIfPossible(e); FMLLog.log(getModId(), Level.FINEST, "Failed to find a usable version.properties file"); return null; } }
public void beginLoading(IFMLSidedHandler handler) { sidedDelegate = handler; FMLLog.info("Attempting early MinecraftForge initialization"); callForgeMethod("initialize"); callForgeMethod("registerCrashCallable"); FMLLog.info("Completed early MinecraftForge initialization"); }
@Subscribe public void buildModList(FMLLoadEvent event) { this.modList = loader.getIndexedModList(); Builder<String, EventBus> eventBus = ImmutableMap.builder(); for (ModContainer mod : loader.getModList()) { EventBus bus = new EventBus(mod.getModId()); boolean isActive = mod.registerBus(bus, this); if (isActive) { Level level = Logger.getLogger(mod.getModId()).getLevel(); FMLLog.log( mod.getModId(), Level.FINE, "Mod Logging channel %s configured at %s level.", level == null ? "default" : level); FMLLog.log(mod.getModId(), Level.INFO, "Activating mod %s", mod.getModId()); activeModList.add(mod); modStates.put(mod.getModId(), ModState.UNLOADED); eventBus.put(mod.getModId(), bus); } else { FMLLog.log( mod.getModId(), Level.WARNING, "Mod %s has been disabled through configuration", mod.getModId()); modStates.put(mod.getModId(), ModState.UNLOADED); modStates.put(mod.getModId(), ModState.DISABLED); } } eventChannels = eventBus.build(); }
private Method gatherAnnotations(Class<?> clazz) throws Exception { Method factoryMethod = null; for (Method m : clazz.getDeclaredMethods()) { for (Annotation a : m.getAnnotations()) { if (modTypeAnnotations.containsKey(a.annotationType())) { Class<?>[] paramTypes = new Class[] {modTypeAnnotations.get(a.annotationType())}; if (Arrays.equals(m.getParameterTypes(), paramTypes)) { m.setAccessible(true); eventMethods.put(modTypeAnnotations.get(a.annotationType()), m); } else { FMLLog.log( getModId(), Level.SEVERE, "The mod %s appears to have an invalid method annotation %s. This annotation can only apply to methods with argument types %s -it will not be called", getModId(), a.annotationType().getSimpleName(), Arrays.toString(paramTypes)); } } else if (a.annotationType().equals(Mod.EventHandler.class)) { if (m.getParameterTypes().length == 1 && modAnnotationTypes.containsKey(m.getParameterTypes()[0])) { m.setAccessible(true); eventMethods.put((Class<? extends FMLEvent>) m.getParameterTypes()[0], m); } else { FMLLog.log( getModId(), Level.SEVERE, "The mod %s appears to have an invalid event annotation %s. This annotation can only apply to methods with recognized event arguments - it will not be called", getModId(), a.annotationType().getSimpleName()); } } else if (a.annotationType().equals(Mod.InstanceFactory.class)) { if (Modifier.isStatic(m.getModifiers()) && m.getParameterTypes().length == 0 && factoryMethod == null) { m.setAccessible(true); factoryMethod = m; } else if (!(Modifier.isStatic(m.getModifiers()) && m.getParameterTypes().length == 0)) { FMLLog.log( getModId(), Level.SEVERE, "The InstanceFactory annotation can only apply to a static method, taking zero arguments - it will be ignored on %s(%s)", m.getName(), Arrays.asList(m.getParameterTypes())); } else if (factoryMethod != null) { FMLLog.log( getModId(), Level.SEVERE, "The InstanceFactory annotation can only be used once, the application to %s(%s) will be ignored", m.getName(), Arrays.asList(m.getParameterTypes())); } } } } return factoryMethod; }
private void initializeLoader() { File modsDir = new File(minecraftDir, "mods"); File configDir = new File(minecraftDir, "config"); String canonicalModsPath; String canonicalConfigPath; try { canonicalModsPath = modsDir.getCanonicalPath(); canonicalConfigPath = configDir.getCanonicalPath(); canonicalConfigDir = configDir.getCanonicalFile(); canonicalModsDir = modsDir.getCanonicalFile(); } catch (IOException ioe) { FMLLog.log( Level.ERROR, ioe, "Failed to resolve loader directories: mods : %s ; config %s", canonicalModsDir.getAbsolutePath(), configDir.getAbsolutePath()); throw new LoaderException(ioe); } if (!canonicalModsDir.exists()) { FMLLog.info("No mod directory found, creating one: %s", canonicalModsPath); boolean dirMade = canonicalModsDir.mkdir(); if (!dirMade) { FMLLog.severe("Unable to create the mod directory %s", canonicalModsPath); throw new LoaderException( String.format("Unable to create the mod directory %s", canonicalModsPath)); } FMLLog.info("Mod directory created successfully"); } if (!canonicalConfigDir.exists()) { FMLLog.fine("No config directory found, creating one: %s", canonicalConfigPath); boolean dirMade = canonicalConfigDir.mkdir(); if (!dirMade) { FMLLog.severe("Unable to create the config directory %s", canonicalConfigPath); throw new LoaderException(); } FMLLog.info("Config directory created successfully"); } if (!canonicalModsDir.isDirectory()) { FMLLog.severe("Attempting to load mods from %s, which is not a directory", canonicalModsPath); throw new LoaderException(); } if (!configDir.isDirectory()) { FMLLog.severe( "Attempting to load configuration from %s, which is not a directory", canonicalConfigPath); throw new LoaderException(); } readInjectedDependencies(); }
public ModMetadata(JsonNode node) { Map<JsonStringNode, Object> processedFields = Maps.transformValues(node.getFields(), new JsonStringConverter()); modId = (String) processedFields.get(aStringBuilder("modid")); if (Strings.isNullOrEmpty(modId)) { FMLLog.log(Level.SEVERE, "Found an invalid mod metadata file - missing modid"); throw new LoaderException(); } name = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("name"))); description = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("description"))); url = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("url"))); updateUrl = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("updateUrl"))); logoFile = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("logoFile"))); version = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("version"))); credits = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("credits"))); parent = Strings.nullToEmpty((String) processedFields.get(aStringBuilder("parent"))); authorList = Objects.firstNonNull( ((List<String>) processedFields.get(aStringBuilder("authors"))), Objects.firstNonNull( ((List<String>) processedFields.get(aStringBuilder("authorList"))), authorList)); requiredMods = processReferences(processedFields.get(aStringBuilder("requiredMods")), HashSet.class); dependencies = processReferences(processedFields.get(aStringBuilder("dependencies")), ArrayList.class); dependants = processReferences(processedFields.get(aStringBuilder("dependants")), ArrayList.class); useDependencyInformation = Boolean.parseBoolean( Strings.nullToEmpty( (String) processedFields.get(aStringBuilder("useDependencyInformation")))); }
public void distributeStateMessage(Class<?> customEvent) { try { masterChannel.post(customEvent.newInstance()); } catch (Exception e) { FMLLog.log(Level.SEVERE, e, "An unexpected exception"); throw new LoaderException(e); } }
private void readInjectedDependencies() { File injectedDepFile = new File(getConfigDir(), "injectedDependencies.json"); if (!injectedDepFile.exists()) { FMLLog.getLogger() .log( Level.DEBUG, "File {} not found. No dependencies injected", injectedDepFile.getAbsolutePath()); return; } JsonParser parser = new JsonParser(); JsonElement injectedDeps; try { injectedDeps = parser.parse(new FileReader(injectedDepFile)); for (JsonElement el : injectedDeps.getAsJsonArray()) { JsonObject jo = el.getAsJsonObject(); String modId = jo.get("modId").getAsString(); JsonArray deps = jo.get("deps").getAsJsonArray(); for (JsonElement dep : deps) { JsonObject depObj = dep.getAsJsonObject(); String type = depObj.get("type").getAsString(); if (type.equals("before")) { injectedBefore.put( modId, VersionParser.parseVersionReference(depObj.get("target").getAsString())); } else if (type.equals("after")) { injectedAfter.put( modId, VersionParser.parseVersionReference(depObj.get("target").getAsString())); } else { FMLLog.getLogger().log(Level.ERROR, "Invalid dependency type {}", type); throw new RuntimeException("Unable to parse type"); } } } } catch (Exception e) { FMLLog.getLogger().log(Level.ERROR, "Unable to parse {} - skipping", injectedDepFile); FMLLog.getLogger().throwing(Level.ERROR, e); return; } FMLLog.getLogger() .log( Level.DEBUG, "Loaded {} injected dependencies on modIds: {}", injectedBefore.size(), injectedBefore.keySet()); }
public BiMap<ModContainer, Object> getModObjectList() { if (modObjectList == null) { FMLLog.severe( "Detected an attempt by a mod %s to perform game activity during mod construction. This is a serious programming error.", activeContainer); return buildModObjectList(); } return ImmutableBiMap.copyOf(modObjectList); }
public boolean serverStarting(Object server) { try { modController.distributeStateMessage(LoaderState.SERVER_STARTING, server); modController.transition(LoaderState.SERVER_STARTING, false); } catch (Throwable t) { FMLLog.log(Level.ERROR, t, "A fatal exception occurred during the server starting event"); return false; } return true; }
/** * Not a fully fleshed out API, may change in future MC versions. However feel free to use and * suggest additions. */ public static void pop(ProgressBar bar) { if (bar.getSteps() != bar.getStep()) throw new IllegalStateException("can't pop unfinished ProgressBar " + bar.getTitle()); bars.remove(bar); if (bar.getSteps() != 0) { long newTime = System.nanoTime(); if (bar.timeEachStep) FMLLog.fine( "Bar Step: %s - %s took %.3fs", bar.getTitle(), bar.getMessage(), ((float) (newTime - bar.lastTime) / 1000000 / 1000)); if (bar.getSteps() == 1) FMLLog.fine( "Bar Finished: %s - %s took %.3fs", bar.getTitle(), bar.getMessage(), ((float) (newTime - bar.startTime) / 1000000 / 1000)); else FMLLog.fine( "Bar Finished: %s took %.3fs", bar.getTitle(), ((float) (newTime - bar.startTime) / 1000000 / 1000)); } FMLCommonHandler.instance().processWindowMessages(); }
@Override public boolean registerBus(EventBus bus, LoadController controller) { if (this.enabled) { FMLLog.log(getModId(), Level.FINE, "Enabling mod %s", getModId()); this.eventBus = bus; this.controller = controller; eventBus.register(this); return true; } else { return false; } }
@Override public void bindMetadata(MetadataCollection mc) { modMetadata = mc.getMetadataForId(getModId(), descriptor); if (descriptor.containsKey("useMetadata")) { overridesMetadata = !((Boolean) descriptor.get("useMetadata")).booleanValue(); } if (overridesMetadata || !modMetadata.useDependencyInformation) { Set<ArtifactVersion> requirements = Sets.newHashSet(); List<ArtifactVersion> dependencies = Lists.newArrayList(); List<ArtifactVersion> dependants = Lists.newArrayList(); annotationDependencies = (String) descriptor.get("dependencies"); Loader.instance() .computeDependencies(annotationDependencies, requirements, dependencies, dependants); modMetadata.requiredMods = requirements; modMetadata.dependencies = dependencies; modMetadata.dependants = dependants; FMLLog.finest("Parsed dependency info : %s %s %s", requirements, dependencies, dependants); } else { FMLLog.finest( "Using mcmod dependency info : %s %s %s", modMetadata.requiredMods, modMetadata.dependencies, modMetadata.dependants); } if (Strings.isNullOrEmpty(modMetadata.name)) { FMLLog.info( "Mod %s is missing the required element 'name'. Substituting %s", getModId(), getModId()); modMetadata.name = getModId(); } internalVersion = (String) descriptor.get("version"); if (Strings.isNullOrEmpty(internalVersion)) { Properties versionProps = searchForVersionProperties(); if (versionProps != null) { internalVersion = versionProps.getProperty(getModId() + ".version"); FMLLog.fine( "Found version %s for mod %s in version.properties, using", internalVersion, getModId()); } } if (Strings.isNullOrEmpty(internalVersion) && !Strings.isNullOrEmpty(modMetadata.version)) { FMLLog.warning( "Mod %s is missing the required element 'version' and a version.properties file could not be found. Falling back to metadata version %s", getModId(), modMetadata.version); internalVersion = modMetadata.version; } if (Strings.isNullOrEmpty(internalVersion)) { FMLLog.warning( "Mod %s is missing the required element 'version' and no fallback can be found. Substituting '1.0'.", getModId()); modMetadata.version = internalVersion = "1.0"; } String mcVersionString = (String) descriptor.get("acceptedMinecraftVersions"); if (!Strings.isNullOrEmpty(mcVersionString)) { minecraftAccepted = VersionParser.parseRange(mcVersionString); } else { minecraftAccepted = Loader.instance().getMinecraftModContainer().getStaticVersionRange(); } }
public void step(String message) { if (step >= steps) throw new IllegalStateException("too much steps for ProgressBar " + title); if (timeEachStep && step != 0) { long newTime = System.nanoTime(); FMLLog.fine( "Bar Step: %s - %s took %.3fs", getTitle(), getMessage(), ((float) (newTime - lastTime) / 1000000 / 1000)); lastTime = newTime; } step++; this.message = FMLCommonHandler.instance().stripSpecialChars(message); FMLCommonHandler.instance().processWindowMessages(); }
@Subscribe public void propogateStateMessage(FMLEvent stateEvent) { if (stateEvent instanceof FMLPreInitializationEvent) { modObjectList = buildModObjectList(); } for (ModContainer mc : activeModList) { activeContainer = mc; String modId = mc.getModId(); stateEvent.applyModContainer(activeContainer()); FMLLog.log( modId, Level.FINEST, "Sending event %s to mod %s", stateEvent.getEventType(), modId); eventChannels.get(modId).post(stateEvent); FMLLog.log(modId, Level.FINEST, "Sent event %s to mod %s", stateEvent.getEventType(), modId); activeContainer = null; if (stateEvent instanceof FMLStateEvent) { if (!errors.containsKey(modId)) { modStates.put(modId, ((FMLStateEvent) stateEvent).getModState()); } else { modStates.put(modId, ModState.ERRORED); } } } }
public void preinitializeMods() { if (!modController.isInState(LoaderState.PREINITIALIZATION)) { FMLLog.warning("There were errors previously. Not beginning mod initialization phase"); return; } ObjectHolderRegistry.INSTANCE.findObjectHolders(discoverer.getASMTable()); ItemStackHolderInjector.INSTANCE.findHolders(discoverer.getASMTable()); modController.distributeStateMessage( LoaderState.PREINITIALIZATION, discoverer.getASMTable(), canonicalConfigDir); ObjectHolderRegistry.INSTANCE.applyObjectHolders(); ItemStackHolderInjector.INSTANCE.inject(); modController.transition(LoaderState.INITIALIZATION, false); progressBar.step("Initializing Minecraft Engine"); }
@Override public void readData( SaveHandler handler, WorldInfo info, Map<String, NBTBase> propertyMap, NBTTagCompound tag) { if (tag.hasKey("ModList")) { NBTTagList modList = tag.getTagList("ModList"); for (int i = 0; i < modList.tagCount(); i++) { NBTTagCompound mod = (NBTTagCompound) modList.tagAt(i); String modId = mod.getString("ModId"); String modVersion = mod.getString("ModVersion"); ModContainer container = Loader.instance().getIndexedModList().get(modId); if (container == null) { FMLLog.log( "fml.ModTracker", Level.SEVERE, "This world was saved with mod %s which appears to be missing, things may not work well", modId); continue; } if (!modVersion.equals(container.getVersion())) { FMLLog.log( "fml.ModTracker", Level.INFO, "This world was saved with mod %s version %s and it is now at version %s, things may not work well", modId, modVersion, container.getVersion()); } } } if (tag.hasKey("ModItemData")) { NBTTagList modList = tag.getTagList("ModItemData"); Set<ItemData> worldSaveItems = GameData.buildWorldItemData(modList); GameData.validateWorldSave(worldSaveItems); } else { GameData.validateWorldSave(null); } }
public static void inject( ModContainer mod, ASMDataTable data, Side side, ILanguageAdapter languageAdapter) { FMLLog.fine("Attempting to inject @SidedProxy classes into %s", mod.getModId()); Set<ASMData> targets = data.getAnnotationsFor(mod).get(SidedProxy.class.getName()); ClassLoader mcl = Loader.instance().getModClassLoader(); for (ASMData targ : targets) { try { Class<?> proxyTarget = Class.forName(targ.getClassName(), true, mcl); Field target = proxyTarget.getDeclaredField(targ.getObjectName()); if (target == null) { // Impossible? FMLLog.severe( "Attempted to load a proxy type into %s.%s but the field was not found", targ.getClassName(), targ.getObjectName()); throw new LoaderException(); } SidedProxy annotation = target.getAnnotation(SidedProxy.class); if (!Strings.isNullOrEmpty(annotation.modId()) && !annotation.modId().equals(mod.getModId())) { FMLLog.fine( "Skipping proxy injection for %s.%s since it is not for mod %s", targ.getClassName(), targ.getObjectName(), mod.getModId()); continue; } String targetType = side.isClient() ? annotation.clientSide() : annotation.serverSide(); Object proxy = Class.forName(targetType, true, mcl).newInstance(); if (languageAdapter.supportsStatics() && (target.getModifiers() & Modifier.STATIC) == 0) { FMLLog.severe( "Attempted to load a proxy type %s into %s.%s, but the field is not static", targetType, targ.getClassName(), targ.getObjectName()); throw new LoaderException(); } if (!target.getType().isAssignableFrom(proxy.getClass())) { FMLLog.severe( "Attempted to load a proxy type %s into %s.%s, but the types don't match", targetType, targ.getClassName(), targ.getObjectName()); throw new LoaderException(); } languageAdapter.setProxy(target, proxyTarget, proxy); } catch (Exception e) { FMLLog.log( Level.SEVERE, e, "An error occured trying to load a proxy into %s.%s", targ.getAnnotationInfo(), targ.getClassName(), targ.getObjectName()); throw new LoaderException(e); } } // Allow language specific proxy injection. languageAdapter.setInternalProxies(mod, side, mcl); }
boolean checkRemoteModList(Map<String, String> modList, Side side) { Set<String> remoteModIds = modList.keySet(); Set<String> localModIds = namedMods.keySet(); Set<String> difference = Sets.newLinkedHashSet(Sets.difference(localModIds, remoteModIds)); for (Iterator<String> iterator = difference.iterator(); iterator.hasNext(); ) { String missingRemotely = iterator.next(); ModState modState = modController.getModState(namedMods.get(missingRemotely)); if (modState == ModState.DISABLED) { iterator.remove(); } } if (difference.size() > 0) FMLLog.info("Attempting connection with missing mods %s at %s", difference, side); return true; }
/** * The primary loading code * * <p>The found resources are first loaded into the {@link #modClassLoader} (always) then scanned * for class resources matching the specification above. * * <p>If they provide the {@link Mod} annotation, they will be loaded as "FML mods" * * <p>Finally, if they are successfully loaded as classes, they are then added to the available * mod list. */ private ModDiscoverer identifyMods() { FMLLog.fine("Building injected Mod Containers %s", injectedContainers); // Add in the MCP mod container mods.add(new InjectedModContainer(mcp, new File("minecraft.jar"))); for (String cont : injectedContainers) { ModContainer mc; try { mc = (ModContainer) Class.forName(cont, true, modClassLoader).newInstance(); } catch (Exception e) { FMLLog.log( Level.ERROR, e, "A problem occured instantiating the injected mod container %s", cont); throw new LoaderException(e); } mods.add(new InjectedModContainer(mc, mc.getSource())); } ModDiscoverer discoverer = new ModDiscoverer(); FMLLog.fine( "Attempting to load mods contained in the minecraft jar file and associated classes"); discoverer.findClasspathMods(modClassLoader); FMLLog.fine("Minecraft jar mods loaded successfully"); FMLLog.getLogger() .log( Level.INFO, "Found {} mods from the command line. Injecting into mod discoverer", ModListHelper.additionalMods.size()); FMLLog.info("Searching %s for mods", canonicalModsDir.getAbsolutePath()); discoverer.findModDirMods( canonicalModsDir, ModListHelper.additionalMods.values().toArray(new File[0])); File versionSpecificModsDir = new File(canonicalModsDir, mccversion); if (versionSpecificModsDir.isDirectory()) { FMLLog.info("Also searching %s for mods", versionSpecificModsDir); discoverer.findModDirMods(versionSpecificModsDir); } mods.addAll(discoverer.identifyMods()); identifyDuplicates(mods); namedMods = Maps.uniqueIndex(mods, new ModIdFunction()); FMLLog.info( "Forge Mod Loader has identified %d mod%s to load", mods.size(), mods.size() != 1 ? "s" : ""); return discoverer; }
public ImmutableBiMap<ModContainer, Object> buildModObjectList() { ImmutableBiMap.Builder<ModContainer, Object> builder = ImmutableBiMap.<ModContainer, Object>builder(); for (ModContainer mc : activeModList) { if (!mc.isImmutable() && mc.getMod() != null) { builder.put(mc, mc.getMod()); } if (mc.getMod() == null && !mc.isImmutable() && state != LoaderState.CONSTRUCTING) { FMLLog.severe( "There is a severe problem with %s - it appears not to have constructed correctly", mc.getModId()); if (state != LoaderState.CONSTRUCTING) { this.errorOccurred(mc, new RuntimeException()); } } } return builder.build(); }
private Loader() { modClassLoader = new ModClassLoader(getClass().getClassLoader()); if (!mccversion.equals(MC_VERSION)) { FMLLog.severe( "This version of FML is built for Minecraft %s, we have detected Minecraft %s in your minecraft jar file", mccversion, MC_VERSION); throw new LoaderException( String.format( "This version of FML is built for Minecraft %s, we have detected Minecraft %s in your minecraft jar file", mccversion, MC_VERSION)); } minecraft = new MinecraftDummyContainer(MC_VERSION); mcp = new MCPDummyContainer( MetadataCollection.from(getClass().getResourceAsStream("/mcpmod.info"), "MCP") .getMetadataForId("mcp", null)); }
public void initializeMods() { progressBar.step("Initializing mods Phase 2"); // Mod controller should be in the initialization state here modController.distributeStateMessage(LoaderState.INITIALIZATION); progressBar.step("Initializing mods Phase 3"); modController.transition(LoaderState.POSTINITIALIZATION, false); modController.distributeStateMessage(FMLInterModComms.IMCEvent.class); ItemStackHolderInjector.INSTANCE.inject(); modController.distributeStateMessage(LoaderState.POSTINITIALIZATION); progressBar.step("Finishing up"); modController.transition(LoaderState.AVAILABLE, false); modController.distributeStateMessage(LoaderState.AVAILABLE); GameData.freezeData(); FMLLog.info( "Forge Mod Loader has successfully loaded %d mod%s", mods.size(), mods.size() == 1 ? "" : "s"); progressBar.step("Completing Minecraft initialization"); }
private void disableRequestedMods() { String forcedModList = System.getProperty("fml.modStates", ""); FMLLog.finer("Received a system property request \'%s\'", forcedModList); Map<String, String> sysPropertyStateList = Splitter.on(CharMatcher.anyOf(";:")) .omitEmptyStrings() .trimResults() .withKeyValueSeparator("=") .split(forcedModList); FMLLog.finer( "System property request managing the state of %d mods", sysPropertyStateList.size()); Map<String, String> modStates = Maps.newHashMap(); forcedModFile = new File(canonicalConfigDir, "fmlModState.properties"); Properties forcedModListProperties = new Properties(); if (forcedModFile.exists() && forcedModFile.isFile()) { FMLLog.finer("Found a mod state file %s", forcedModFile.getName()); try { forcedModListProperties.load(new FileReader(forcedModFile)); FMLLog.finer("Loaded states for %d mods from file", forcedModListProperties.size()); } catch (Exception e) { FMLLog.log(Level.INFO, e, "An error occurred reading the fmlModState.properties file"); } } modStates.putAll(Maps.fromProperties(forcedModListProperties)); modStates.putAll(sysPropertyStateList); FMLLog.fine("After merging, found state information for %d mods", modStates.size()); Map<String, Boolean> isEnabled = Maps.transformValues( modStates, new Function<String, Boolean>() { @Override public Boolean apply(String input) { return Boolean.parseBoolean(input); } }); for (Map.Entry<String, Boolean> entry : isEnabled.entrySet()) { if (namedMods.containsKey(entry.getKey())) { FMLLog.info("Setting mod %s to enabled state %b", entry.getKey(), entry.getValue()); namedMods.get(entry.getKey()).setEnabledState(entry.getValue()); } } }
private Multimap<Class<? extends Annotation>, Object> gatherAnnotations(Class<?> clazz) throws Exception { Multimap<Class<? extends Annotation>, Object> anns = ArrayListMultimap.create(); for (Method m : clazz.getDeclaredMethods()) { for (Annotation a : m.getAnnotations()) { if (modTypeAnnotations.containsKey(a.annotationType())) { Class<?>[] paramTypes = new Class[] {modTypeAnnotations.get(a.annotationType())}; if (Arrays.equals(m.getParameterTypes(), paramTypes)) { m.setAccessible(true); anns.put(a.annotationType(), m); } else { FMLLog.severe( "The mod %s appears to have an invalid method annotation %s. This annotation can only apply to methods with argument types %s -it will not be called", getModId(), a.annotationType().getSimpleName(), Arrays.toString(paramTypes)); } } } } return anns; }
@Subscribe public void constructMod(FMLConstructionEvent event) { try { ModClassLoader modClassLoader = event.getModClassLoader(); modClassLoader.addFile(source); // MCPC - show users what mod is being loaded in case a crash occurs FMLLog.fine("Constructing mod from file source : " + source); Class<?> clazz = Class.forName(className, true, modClassLoader); ASMDataTable asmHarvestedAnnotations = event.getASMHarvestedData(); // TODO asmHarvestedAnnotations.getAnnotationsFor(this); annotations = gatherAnnotations(clazz); isNetworkMod = FMLNetworkHandler.instance().registerNetworkMod(this, clazz, event.getASMHarvestedData()); modInstance = clazz.newInstance(); ProxyInjector.inject( this, event.getASMHarvestedData(), FMLCommonHandler.instance().getSide()); processFieldAnnotations(event.getASMHarvestedData()); } catch (Throwable e) { controller.errorOccurred(this, e); Throwables.propagateIfPossible(e); } }
private void identifyDuplicates(List<ModContainer> mods) { TreeMultimap<ModContainer, File> dupsearch = TreeMultimap.create(new ModIdComparator(), Ordering.arbitrary()); for (ModContainer mc : mods) { if (mc.getSource() != null) { dupsearch.put(mc, mc.getSource()); } } ImmutableMultiset<ModContainer> duplist = Multisets.copyHighestCountFirst(dupsearch.keys()); SetMultimap<ModContainer, File> dupes = LinkedHashMultimap.create(); for (Entry<ModContainer> e : duplist.entrySet()) { if (e.getCount() > 1) { FMLLog.severe( "Found a duplicate mod %s at %s", e.getElement().getModId(), dupsearch.get(e.getElement())); dupes.putAll(e.getElement(), dupsearch.get(e.getElement())); } } if (!dupes.isEmpty()) { throw new DuplicateModsFoundException(dupes); } }