Things. they work. Obviously still WAY more to do.

This commit is contained in:
cpw authored and LexManos committed 2018-09-05 11:53:54 -07:00
1 parent 1b1ee6f0b8
commit baa9dfe55a
95 files changed
+852 -786

No files matched your search

@@ -49,7 +49,7 @@ import net.minecraftforge.fml.client.config.GuiConfigEntries.SelectValueEntry;
import net.minecraftforge.fml.client.config.GuiConfigEntries.BooleanEntry;
import net.minecraftforge.fml.client.config.IConfigElement;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import static net.minecraftforge.common.ForgeModContainer.VERSION_CHECK_CAT;
/**
@@ -52,7 +52,7 @@ import net.minecraftforge.common.util.Constants;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
@@ -145,7 +145,7 @@ import net.minecraftforge.fluids.IFluidBlock;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.LoaderState;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher;
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.ConnectionType;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
@@ -71,7 +71,7 @@ import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.oredict.OreDictionary;
import net.minecraftforge.oredict.OreIngredient;
@@ -26,7 +26,7 @@ import org.apache.commons.lang3.Validate;
import com.google.common.collect.ImmutableList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.eventbus.api.GenericEvent;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.IForgeRegistryEntry;
@@ -46,7 +46,7 @@ import com.google.common.collect.Sets;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.registries.IRegistryDelegate;
@@ -0,0 +1,73 @@
/*
* Minecraft Forge
* Copyright (c) 2018.
*
* 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 version 2.1
* of the License.
*
* 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.fml;
import net.minecraftforge.api.Side;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.language.ModFileScanData;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.objectweb.asm.Type;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import static net.minecraftforge.fml.Logging.LOADING;
/**
* Automatic eventbus subscriber - reads {@link net.minecraftforge.fml.common.Mod.EventBusSubscriber}
* annotations and passes the class instances to the {@link net.minecraftforge.common.MinecraftForge.EVENT_BUS}
*/
public class AutomaticEventSubscriber
{
private static final Logger LOGGER = LogManager.getLogger("FML");
public static void inject(final ModContainer mod, final ModFileScanData scanData, final ClassLoader loader)
{
LOGGER.debug(LOADING,"Attempting to inject @EventBusSubscriber classes into the eventbus for {}", mod.getModId());
List<ModFileScanData.AnnotationData> ebsTargets = scanData.getAnnotations().stream().
filter(annotationData -> Objects.equals(annotationData.getAnnotationType(), Type.getType(Mod.EventBusSubscriber.class))).
collect(Collectors.toList());
ebsTargets.forEach(ad -> {
final List<ModAnnotation.EnumHolder> sidesValue = (List<ModAnnotation.EnumHolder>)ad.getAnnotationData().get("value");
final EnumSet<Side> sides = sidesValue.stream().map(eh -> Side.valueOf(eh.getValue())).
collect(Collectors.toCollection(() -> EnumSet.noneOf(Side.class)));
final String modId = (String)ad.getAnnotationData().getOrDefault("modId", mod.getModId());
if (Objects.equals(mod.getModId(), modId) && sides.contains(FMLEnvironment.side)) {
try
{
MinecraftForge.EVENT_BUS.register(Class.forName(ad.getClassType().getClassName(), true, loader));
}
catch (ClassNotFoundException e)
{
LOGGER.error(LOADING, "Failed to load mod class {} for @EventBusSubscriber annotation", ad.getClassType(), e);
throw new RuntimeException(e);
}
}
});
}
}
@@ -19,53 +19,14 @@
package net.minecraftforge.fml;
import com.electronwill.nightconfig.core.path.PathConfig;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import net.minecraftforge.fml.loading.DefaultModInfos;
public class DefaultModContainers
{
static {
PathConfig minecraftmod;
PathConfig forgemod;
try
{
minecraftmod = PathConfig.of(Paths.get(DefaultModContainers.class.getClassLoader().getResource("minecraftmod.toml").toURI()));
forgemod = PathConfig.of(Paths.get(DefaultModContainers.class.getClassLoader().getResource("forgemod.toml").toURI()));
minecraftmod.load();
forgemod.load();
}
catch (URISyntaxException | NullPointerException e)
{
throw new RuntimeException("Missing toml configs for minecraft and forge!", e);
}
minecraftModInfo = new ModInfo(null, minecraftmod);
forgeModInfo = new ModInfo(null, forgemod);
}
private static final IModInfo minecraftModInfo;
private static final IModInfo forgeModInfo;
// no construction
private DefaultModContainers() {}
public static List<IModInfo> getModInfos()
{
return Arrays.asList(minecraftModInfo, forgeModInfo);
}
public static final ModContainer MINECRAFT = new ModContainer(minecraftModInfo)
public static final ModContainer MINECRAFT = new ModContainer(DefaultModInfos.minecraftModInfo)
{
@Override
public boolean matches(Object mod)
public boolean matches(final Object mod)
{
return mod == this;
}
@@ -76,4 +37,4 @@ public class DefaultModContainers
return this;
}
};
}
}
@@ -59,6 +59,7 @@ public class LaunchTesting
logcontext.getConfiguration().addFilter(axformFilter);
logcontext.getConfiguration().addFilter(eventbusFilter);
logcontext.updateLoggers();
System.setProperty("fml.explodedDir", "/home/cpw/projects/mods/inventorysorter/classes");
hackNatives();
Launcher.main("--launchTarget", "devfmlclient","--gameDir", "projects/run",
"--accessToken", "blah", "--version", "FMLDev", "--assetIndex", "1.12",
@@ -20,18 +20,18 @@
package net.minecraftforge.fml;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.loading.ModList;
import net.minecraftforge.fml.loading.ModLoadingStage;
import net.minecraftforge.fml.common.event.ModLifecycleEvent;
import net.minecraftforge.fml.javafmlmod.FMLModContainer;
import java.util.function.Supplier;
public enum LifecycleEventProvider
{
LOAD(()->new LifecycleEvent(ModLoadingStage.BEGIN)),
PREINIT(()->new LifecycleEvent(ModLoadingStage.PREINIT));
CONSTRUCT(()->new LifecycleEvent(ModLoadingStage.CONSTRUCT));
public void dispatch(final ModList target) {
target.dispatchLifeCycleEvent(this.event.get());
public void dispatch() {
ModList.get().dispatchLifeCycleEvent(this.event.get());
}
private final Supplier<? extends LifecycleEvent> event;
@@ -41,7 +41,7 @@ public enum LifecycleEventProvider
}
public static class LifecycleEvent extends Event {
public static class LifecycleEvent {
private final ModLoadingStage stage;
public LifecycleEvent(ModLoadingStage stage)
@@ -59,5 +59,9 @@ public enum LifecycleEventProvider
return ModLoadingStage.values()[this.stage.ordinal()+1];
}
public ModLifecycleEvent buildModEvent(FMLModContainer fmlModContainer)
{
return stage.getModEvent(fmlModContainer);
}
}
}
@@ -17,14 +17,19 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.language;
package net.minecraftforge.fml;
import net.minecraftforge.fml.LifecycleEventProvider;
import net.minecraftforge.fml.loading.ModLoadingStage;
import net.minecraftforge.fml.language.ExtensionPoint;
import net.minecraftforge.fml.language.IModInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* The container that wraps around mods in the system.
@@ -45,11 +50,15 @@ public abstract class ModContainer
protected final IModInfo modInfo;
protected ModLoadingStage modLoadingStage;
protected final Map<ModLoadingStage, Consumer<LifecycleEventProvider.LifecycleEvent>> triggerMap;
protected final Map<ExtensionPoint, Supplier<?>> extensionPoints = new IdentityHashMap<>();
protected final List<Throwable> modLoadingError;
public ModContainer(IModInfo info)
{
this.modId = info.getModId();
this.modInfo = info;
this.triggerMap = new HashMap<>();
this.modLoadingError = new ArrayList<>();
this.modLoadingStage = ModLoadingStage.BEGIN;
}
@@ -83,7 +92,7 @@ public abstract class ModContainer
*/
public final void transitionState(LifecycleEventProvider.LifecycleEvent event)
{
if (modLoadingStage != event.fromStage())
if (modLoadingStage == event.fromStage())
{
try
{
@@ -105,6 +114,16 @@ public abstract class ModContainer
return modInfo;
}
@SuppressWarnings("unchecked")
public <T> Optional<T> getCustomExtension(ExtensionPoint point) {
return Optional.ofNullable((T)extensionPoints.getOrDefault(point,()-> null).get());
}
public <T> void registerExtensionPoint(ExtensionPoint point, Supplier<T> extension)
{
extensionPoints.put(point, extension);
}
/**
* Does this mod match the supplied mod?
*
@@ -117,6 +136,4 @@ public abstract class ModContainer
* @return the mod object instance
*/
public abstract Object getMod();
public abstract <T> T getCustomExtension(final String name);
}
@@ -0,0 +1,114 @@
/*
* Minecraft Forge
* Copyright (c) 2018.
*
* 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 version 2.1
* of the License.
*
* 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.fml;
import com.google.common.collect.Streams;
import net.minecraftforge.fml.loading.DefaultModInfos;
import net.minecraftforge.fml.loading.moddiscovery.BackgroundScanHandler;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* Master list of all mods
*/
public class ModList
{
private static ModList INSTANCE;
private final List<ModFileInfo> modFiles;
private final List<ModInfo> sortedList;
private final Map<String, ModFileInfo> fileById;
private BackgroundScanHandler scanner;
private List<ModContainer> mods;
private Map<String, ModContainer> indexedMods;
private ModList(final List<ModFile> modFiles, final List<ModInfo> sortedList)
{
this.modFiles = modFiles.stream().map(ModFile::getModFileInfo).map(ModFileInfo.class::cast).collect(Collectors.toList());
this.sortedList = Streams.concat(DefaultModInfos.getModInfos().stream(), sortedList.stream()).
map(ModInfo.class::cast).
collect(Collectors.toList());
this.fileById = this.modFiles.stream().map(ModFileInfo::getMods).flatMap(Collection::stream).
map(ModInfo.class::cast).
collect(Collectors.toMap(ModInfo::getModId, ModInfo::getOwningFile));
}
public static ModList of(List<ModFile> modFiles, List<ModInfo> sortedList)
{
INSTANCE = new ModList(modFiles, sortedList);
return INSTANCE;
}
public static ModList get() {
return INSTANCE;
}
public List<ModFileInfo> getModFiles()
{
return modFiles;
}
public ModFileInfo getModFileById(String modid)
{
return this.fileById.get(modid);
}
public void dispatchLifeCycleEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent) {
this.mods.parallelStream().forEach(m->m.transitionState(lifecycleEvent));
final List<ModContainer> erroredContainers = this.mods.stream().filter(m -> m.getCurrentState() == ModLoadingStage.ERROR).collect(Collectors.toList());
if (!erroredContainers.isEmpty()) {
throw new RuntimeException("Errored containers found!");
}
}
public void setLoadedMods(final List<ModContainer> modContainers)
{
this.mods = modContainers;
this.indexedMods = modContainers.stream().collect(Collectors.toMap(ModContainer::getModId, Function.identity()));
}
public Optional<Object> getModObjectById(String modId)
{
return getModContainerById(modId).map(ModContainer::getMod);
}
public Optional<? extends ModContainer> getModContainerById(String modId)
{
return Optional.ofNullable(this.indexedMods.get(modId));
}
public List<ModInfo> getMods()
{
return this.sortedList;
}
public boolean isLoaded(String modTarget)
{
return this.indexedMods.containsKey(modTarget);
}
}
@@ -0,0 +1,79 @@
/*
* Minecraft Forge
* Copyright (c) 2018.
*
* 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 version 2.1
* of the License.
*
* 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.fml;
import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.loading.LoadingModList;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class ModLoader
{
private static final Logger LOGGER = LogManager.getLogger("FML");
private static ModLoader INSTANCE;
private final ClassLoader launchClassLoader;
private final LoadingModList loadingModList;
private final ModLoadingClassLoader modClassLoader;
private ModLoader()
{
INSTANCE = this;
this.launchClassLoader = FMLLoader.getLaunchClassLoader();
this.loadingModList = FMLLoader.getLoadingModList();
this.modClassLoader = new ModLoadingClassLoader(this.launchClassLoader);
Thread.currentThread().setContextClassLoader(this.modClassLoader);
}
public static ModLoader get()
{
return INSTANCE == null ? INSTANCE = new ModLoader() : INSTANCE;
}
public void loadMods() {
final ModList modList = ModList.of(loadingModList.getModFiles().stream().map(ModFileInfo::getFile).collect(Collectors.toList()), loadingModList.getMods());
modList.setLoadedMods(loadingModList.getModFiles().stream().
map(ModFileInfo::getFile).
map(mf -> buildMods(mf, modClassLoader)).
flatMap(Collection::stream).collect(Collectors.toList()));
LifecycleEventProvider.LOAD.dispatch();
LifecycleEventProvider.CONSTRUCT.dispatch();
}
private List<ModContainer> buildMods(final ModFile modFile, final ModLoadingClassLoader modClassLoader)
{
final Map<String, IModInfo> modInfoMap = modFile.getModFileInfo().getMods().stream().collect(Collectors.toMap(IModInfo::getModId, Function.identity()));
return modFile.getScanResult().getTargets().entrySet().stream().
map(e->e.getValue().<ModContainer>loadMod(modInfoMap.get(e.getKey()), modClassLoader, modFile.getScanResult())).
collect(Collectors.toList());
}
}
@@ -17,15 +17,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.loading;
package net.minecraftforge.fml;
import net.minecraftforge.fml.loading.FMLLoader;
import org.apache.logging.log4j.LogManager;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.SecureClassLoader;
@@ -38,11 +36,8 @@ public class ModLoadingClassLoader extends SecureClassLoader
ClassLoader.registerAsParallelCapable();
}
private ModLoader modLoader;
protected ModLoadingClassLoader(ModLoader modLoader, ClassLoader parent) {
protected ModLoadingClassLoader(final ClassLoader parent) {
super(parent);
this.modLoader = modLoader;
}
@Override
@@ -56,7 +51,7 @@ public class ModLoadingClassLoader extends SecureClassLoader
{
LogManager.getLogger("FML").debug(LOADING, "Loading class {}", name);
final String className = name.replace('.','/').concat(".class");
final Path classResource = modLoader.getModList().findResource(className);
final Path classResource = FMLLoader.getLoadingModList().findResource(className);
if (classResource != null) {
try {
final byte[] bytes = Files.readAllBytes(classResource);
@@ -66,6 +61,8 @@ public class ModLoadingClassLoader extends SecureClassLoader
{
throw new ClassNotFoundException("Failed to load class file " + classResource + " for "+ className, e);
}
} else {
getParent().loadClass(name);
}
throw new ClassNotFoundException("Failed to find class file "+ className);
}
@@ -0,0 +1,52 @@
/*
* Minecraft Forge
* Copyright (c) 2018.
*
* 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 version 2.1
* of the License.
*
* 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.fml;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.ModLifecycleEvent;
import java.util.function.Function;
import java.util.function.Supplier;
public enum ModLoadingStage
{
ERROR(null),
BEGIN(null),
CONSTRUCT(()->FMLPreInitializationEvent::new),
PREINIT(()->FMLInitializationEvent::new),
INIT(()->FMLPostInitializationEvent::new),
POSTINIT(()->FMLLoadCompleteEvent::new),
COMPLETE(null);
private final Supplier<Function<ModContainer, ModLifecycleEvent>> modLifecycleEventFunction;
ModLoadingStage(Supplier<Function<ModContainer, ModLifecycleEvent>> modLifecycleEventFunction)
{
this.modLifecycleEventFunction = modLifecycleEventFunction;
}
public ModLifecycleEvent getModEvent(ModContainer fmlModContainer)
{
return modLifecycleEventFunction.get().apply(fmlModContainer);
}
}
@@ -19,8 +19,6 @@
package net.minecraftforge.fml;
import net.minecraftforge.fml.language.ModContainer;
public class ModThreadContext
{
private static ThreadLocal<ModThreadContext> context = ThreadLocal.withInitial(ModThreadContext::new);
@@ -20,6 +20,7 @@
package net.minecraftforge.fml;
import net.minecraftforge.api.Side;
import net.minecraftforge.fml.loading.FMLEnvironment;
import java.util.concurrent.Callable;
import java.util.function.Supplier;
@@ -37,7 +38,7 @@ public final class SidedExecutor
* @return The callable's result
*/
public static <T> T runOn(Side side, Supplier<Callable<T>> toRun) {
if (side == Side.CLIENT) {
if (side == FMLEnvironment.side) {
try
{
return toRun.get().call();
@@ -49,4 +50,16 @@ public final class SidedExecutor
}
return null;
}
public static <T> T runSided(Supplier<Supplier<T>> clientTarget, Supplier<Supplier<T>> serverTarget) {
switch (FMLEnvironment.side)
{
case CLIENT:
return clientTarget.get().get();
case SERVER:
return serverTarget.get().get();
default:
throw new IllegalArgumentException("UNSIDED?");
}
}
}
@@ -19,7 +19,6 @@
package net.minecraftforge.fml;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.common.versioning.ComparableVersion;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
@@ -27,7 +27,7 @@ import net.minecraft.client.resources.IResourcePack;
import net.minecraft.client.resources.data.MetadataSerializer;
import net.minecraftforge.fml.SidedProvider;
import net.minecraftforge.fml.VersionChecker;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.ModLoader;
import org.lwjgl.input.Mouse;
import java.io.IOException;
@@ -46,7 +46,7 @@ public class ClientModLoader
{
SidedProvider.setClient(()->minecraft);
SplashProgress.start();
FMLLoader.getModLoader().loadMods();
ModLoader.get().loadMods();
minecraft.refreshResources();
}
@@ -21,7 +21,8 @@ package net.minecraftforge.fml.client;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.fml.loading.ModList;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.language.ExtensionPoint;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import java.util.Optional;
@@ -31,6 +32,7 @@ public class ConfigGuiHandler
{
public static Optional<BiFunction<Minecraft, GuiScreen, GuiScreen>> getGuiFactoryFor(ModInfo selectedMod)
{
return ModList.get().getModContainerById(selectedMod.getModId()).map(mc->mc.getCustomExtension("customGuiFactory"));
return ModList.get().getModContainerById(selectedMod.getModId()).
flatMap(mc -> mc.getCustomExtension(ExtensionPoint.GUIFACTORY));
}
}
@@ -24,7 +24,7 @@ import java.util.Set;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.fml.client.config.GuiConfig;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
public class DefaultGuiFactory implements IModGuiFactory
{
@@ -101,7 +101,7 @@ import net.minecraftforge.fml.common.LoaderException;
import net.minecraftforge.fml.common.MetadataCollection;
import net.minecraftforge.fml.common.MissingModsException;
import net.minecraftforge.fml.common.MultipleModsErrored;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.ModMetadata;
import net.minecraftforge.fml.common.StartupQuery;
import net.minecraftforge.fml.common.WrongMinecraftVersionException;
@@ -32,7 +32,7 @@ import javax.imageio.ImageIO;
import net.minecraft.client.resources.FileResourcePack;
import net.minecraftforge.fml.common.FMLContainerHolder;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
public class FMLFileResourcePack extends FileResourcePack implements FMLContainerHolder {
@@ -32,7 +32,7 @@ import javax.imageio.ImageIO;
import net.minecraft.client.resources.FolderResourcePack;
import net.minecraftforge.fml.common.FMLContainerHolder;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
public class FMLFolderResourcePack extends FolderResourcePack implements FMLContainerHolder {
@@ -20,7 +20,7 @@
package net.minecraftforge.fml.client;
import net.minecraftforge.fml.common.DuplicateModsFoundException;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import java.io.File;
import java.util.Map.Entry;
@@ -20,7 +20,7 @@
package net.minecraftforge.fml.client;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.toposort.ModSortingException;
import net.minecraftforge.fml.common.toposort.ModSortingException.SortingExceptionData;
@@ -33,7 +33,7 @@ import net.minecraft.client.resources.IResourcePack;
import net.minecraft.client.resources.SimpleReloadableResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.FMLContainerHolder;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -37,7 +37,7 @@ import net.minecraft.client.resources.I18n;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import org.lwjgl.input.Keyboard;
@@ -52,16 +52,16 @@ import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.VersionChecker;
import net.minecraftforge.fml.client.ConfigGuiHandler;
import net.minecraftforge.fml.client.ResourcePackLoader;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.versioning.ComparableVersion;
import static net.minecraft.util.StringUtils.stripControlCodes;
import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.loading.ModList;
import net.minecraftforge.fml.loading.StringUtils;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import org.apache.commons.lang3.tuple.Pair;
@@ -1,94 +0,0 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* 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 version 2.1
* of the License.
*
* 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.fml.common;
import com.google.common.base.Strings;
import com.google.common.collect.SetMultimap;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation;
import net.minecraftforge.fml.relauncher.Side;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
/**
* Automatic eventbus subscriber - reads {@link net.minecraftforge.fml.common.Mod.EventBusSubscriber}
* annotations and passes the class instances to the {@link net.minecraftforge.common.MinecraftForge.EVENT_BUS}
*/
public class AutomaticEventSubscriber
{
private static final EnumSet<Side> DEFAULT = EnumSet.allOf(Side.class);
public static void inject(ModContainer mod, ASMDataTable data, Side side)
{
FMLLog.log.debug("Attempting to inject @EventBusSubscriber classes into the eventbus for {}", mod.getModId());
SetMultimap<String, ASMData> modData = data.getAnnotationsFor(mod);
Set<ASMDataTable.ASMData> mods = modData.get(Mod.class.getName());
Set<ASMDataTable.ASMData> targets = modData.get(Mod.EventBusSubscriber.class.getName());
ClassLoader mcl = Loader.instance().getModClassLoader();
for (ASMDataTable.ASMData targ : targets)
{
try
{
//noinspection unchecked
@SuppressWarnings("unchecked")
List<ModAnnotation.EnumHolder> sidesEnum = (List<ModAnnotation.EnumHolder>)targ.getAnnotationInfo().get("value");
EnumSet<Side> sides = DEFAULT;
if (sidesEnum != null) {
sides = EnumSet.noneOf(Side.class);
for (ModAnnotation.EnumHolder h: sidesEnum) {
sides.add(Side.valueOf(h.getValue()));
}
}
if (sides == DEFAULT || sides.contains(side)) {
//FMLLog.log.debug("Found @EventBusSubscriber class {}", targ.getClassName());
String amodid = (String)targ.getAnnotationInfo().get("modid");
if (Strings.isNullOrEmpty(amodid)) {
amodid = ASMDataTable.getOwnerModID(mods, targ);
if (Strings.isNullOrEmpty(amodid)) {
FMLLog.bigWarning("Could not determine owning mod for @EventBusSubscriber on {} for mod {}", targ.getClassName(), mod.getModId());
continue;
}
}
if (!mod.getModId().equals(amodid))
{
FMLLog.log.debug("Skipping @EventBusSubscriber injection for {} since it is not for mod {}", targ.getClassName(), mod.getModId());
continue; //We're not injecting this guy
}
FMLLog.log.debug("Registering @EventBusSubscriber for {} for mod {}", targ.getClassName(), mod.getModId());
Class<?> subscriptionTarget = Class.forName(targ.getClassName(), false, mcl);
MinecraftForge.EVENT_BUS.register(subscriptionTarget);
FMLLog.log.debug("Injected @EventBusSubscriber class {}", targ.getClassName());
}
}
catch (Throwable e)
{
FMLLog.log.error("An error occurred trying to load an EventBusSubscriber {} for modid {}", targ.getClassName(), mod.getModId(), e);
throw new LoaderException(e);
}
}
}
}
@@ -62,7 +62,7 @@ import net.minecraftforge.fml.common.gameevent.TickEvent.Phase;
import net.minecraftforge.fml.common.network.FMLNetworkEvent;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.thread.SidedThreadGroup;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.server.FMLServerHandler;
@@ -38,7 +38,7 @@ import net.minecraftforge.fml.common.network.NetworkCheckHandler;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.internal.FMLNetworkHandler;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.GameData;
@@ -119,7 +119,7 @@ public final class FMLContainer extends DummyModContainer implements WorldAccess
mod.setString("ModVersion", mc.getVersion());
modList.appendTag(mod);
}
fmlData.setTag("ModList", modList);
fmlData.setTag("LoadingModList", modList);
NBTTagCompound registries = new NBTTagCompound();
fmlData.setTag("Registries", registries);
@@ -135,9 +135,9 @@ public final class FMLContainer extends DummyModContainer implements WorldAccess
@Override
public void readData(SaveHandler handler, WorldInfo info, Map<String, NBTBase> propertyMap, NBTTagCompound tag)
{
if (tag.hasKey("ModList"))
if (tag.hasKey("LoadingModList"))
{
NBTTagList modList = tag.getTagList("ModList", (byte)10);
NBTTagList modList = tag.getTagList("LoadingModList", (byte)10);
for (int i = 0; i < modList.tagCount(); i++)
{
NBTTagCompound mod = modList.getCompoundTagAt(i);
@@ -19,7 +19,7 @@
package net.minecraftforge.fml.common;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
public interface FMLContainerHolder
{
@@ -29,7 +29,7 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.util.IThreadListener;
import net.minecraftforge.common.util.CompoundDataFixer;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.Side;
public interface IFMLSidedHandler
@@ -24,7 +24,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import net.minecraftforge.fml.javafmlmod.FMLModContainer;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.Side;
public interface ILanguageAdapter {
@@ -31,7 +31,7 @@ import java.util.stream.Stream;
import net.minecraftforge.common.util.TextTable;
import net.minecraftforge.fml.common.LoaderState.ModState;
import net.minecraftforge.fml.common.ProgressManager.ProgressBar;
import net.minecraftforge.fml.common.event.FMLEvent;
import net.minecraftforge.fml.common.event.ModLifecycleEvent;
import net.minecraftforge.fml.common.event.FMLLoadEvent;
import net.minecraftforge.fml.common.event.FMLModDisabledEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
@@ -39,7 +39,7 @@ import net.minecraftforge.fml.common.event.FMLStateEvent;
import net.minecraftforge.fml.common.eventhandler.FMLThrowingEventBus;
import net.minecraftforge.fml.common.versioning.ArtifactVersion;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.ThreadContext;
import org.apache.logging.log4j.message.FormattedMessage;
@@ -175,7 +175,7 @@ public class LoadController
}
@Subscribe
public void propogateStateMessage(FMLEvent stateEvent)
public void propogateStateMessage(ModLifecycleEvent stateEvent)
{
if (stateEvent instanceof FMLPreInitializationEvent)
{
@@ -190,7 +190,7 @@ public class LoadController
ProgressManager.pop(bar);
}
private void sendEventToModContainer(FMLEvent stateEvent, ModContainer mc)
private void sendEventToModContainer(ModLifecycleEvent stateEvent, ModContainer mc)
{
String modId = mc.getModId();
Collection<String> requirements = mc.getRequirements().stream().map(ArtifactVersion::getLabel).collect(Collectors.toCollection(HashSet::new));
@@ -42,8 +42,8 @@ import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.config.ConfigManager;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.fml.common.LoaderState.ModState;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.language.ModContainer.Disableable;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModContainer.Disableable;
import net.minecraftforge.fml.common.ProgressManager.ProgressBar;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import net.minecraftforge.fml.common.discovery.ContainerType;
@@ -24,8 +24,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import net.minecraftforge.fml.client.IModGuiFactory;
import net.minecraftforge.fml.common.event.FMLEvent;
import net.minecraftforge.api.Side;
import net.minecraftforge.fml.common.event.ModLifecycleEvent;
import net.minecraftforge.fml.common.event.FMLFingerprintViolationEvent;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLInterModComms;
@@ -37,15 +37,12 @@ import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.event.FMLServerStoppedEvent;
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
import net.minecraftforge.fml.common.event.FMLInterModComms.IMCEvent;
import net.minecraftforge.fml.common.network.NetworkCheckHandler;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.common.versioning.VersionRange;
import net.minecraftforge.fml.relauncher.Side;
/**
* This defines a Mod to FML.
* Any class found with this annotation applied will be loaded as a Mod. The instance that is loaded will
* represent the mod to other Mods in the system. It will be sent various subclasses of {@link FMLEvent}
* represent the mod to other Mods in the system. It will be sent various subclasses of {@link ModLifecycleEvent}
* at pre-defined times during the loading of the game, based on where you have applied the {@link EventHandler}
* annotation.
*/
@@ -60,7 +57,7 @@ public @interface Mod
* This will be used to identify your mod for third parties (other mods), it will be used to identify your mod for registries such as block and item registries.
* By default, you will have a resource domain that matches the modid. All these uses require that constraints are imposed on the format of the modid.
*/
String modid();
String value();
/**
* Marks the associated method as handling an FML lifecycle event.
* The method must have a single parameter, one of the following types. This annotation
@@ -105,20 +102,6 @@ public @interface Mod
@Target(ElementType.METHOD)
@interface EventHandler{}
/**
* Populate the annotated field with the mod instance based on the specified ModId. This can be used
* to retrieve instances of other mods.
* @author cpw
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Instance {
/**
* The mod object to inject into this field
*/
String value() default "";
}
/**
* A class which will be subscribed to {@link net.minecraftforge.common.MinecraftForge.EVENT_BUS} at mod construction time.
*/
@@ -26,7 +26,7 @@ import java.util.Map;
import net.minecraftforge.fml.common.discovery.ModCandidate;
import net.minecraftforge.fml.common.discovery.asm.ASMModParser;
import net.minecraftforge.fml.javafmlmod.FMLModContainer;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation;
import org.objectweb.asm.Type;
@@ -28,7 +28,7 @@ import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gson.annotations.SerializedName;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
/**
* @author cpw
@@ -25,7 +25,7 @@ import java.util.Set;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.Side;
import com.google.common.base.Strings;
@@ -24,6 +24,7 @@ import net.minecraftforge.fml.client.GuiWrongMinecraft;
import net.minecraftforge.fml.client.IDisplayableError;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.fml.ModContainer;
public class WrongMinecraftVersionException extends EnhancedRuntimeException implements IDisplayableError
{
@@ -34,7 +34,7 @@ import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
public class ASMDataTable
{
@@ -21,7 +21,7 @@ package net.minecraftforge.fml.common.discovery;
import java.util.List;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
public enum ContainerType
{
@@ -30,7 +30,7 @@ import java.util.regex.Matcher;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.LoaderException;
import net.minecraftforge.fml.common.MetadataCollection;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.ModContainerFactory;
import net.minecraftforge.fml.common.discovery.asm.ASMModParser;
@@ -22,7 +22,7 @@ package net.minecraftforge.fml.common.discovery;
import java.util.List;
import java.util.regex.Pattern;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
public interface ITypeDiscoverer
{
@@ -30,7 +30,7 @@ import java.util.jar.JarFile;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.LoaderException;
import net.minecraftforge.fml.common.MetadataCollection;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.ModContainerFactory;
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
import net.minecraftforge.fml.common.discovery.asm.ASMModParser;
@@ -23,7 +23,7 @@ import java.io.File;
import java.util.List;
import java.util.Set;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
@@ -25,7 +25,7 @@ import java.util.List;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.LoaderException;
import net.minecraftforge.fml.common.ModClassLoader;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.CoreModManager;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@@ -1,65 +0,0 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* 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 version 2.1
* of the License.
*
* 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.fml.common.event;
import net.minecraftforge.fml.common.ModClassLoader;
import net.minecraftforge.fml.common.LoaderState.ModState;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import com.google.common.collect.ListMultimap;
/**
* An internal FML event used to signal the construction of mods. Should not be used by mods.
*/
public class FMLConstructionEvent extends FMLStateEvent
{
private ModClassLoader modClassLoader;
private ASMDataTable asmData;
private ListMultimap<String,String> reverseDependencies;
@SuppressWarnings("unchecked")
public FMLConstructionEvent(Object... eventData)
{
this.modClassLoader = (ModClassLoader)eventData[0];
this.asmData = (ASMDataTable) eventData[1];
this.reverseDependencies = (ListMultimap<String, String>) eventData[2];
}
public ModClassLoader getModClassLoader()
{
return modClassLoader;
}
@Override
public ModState getModState()
{
return ModState.CONSTRUCTED;
}
public ASMDataTable getASMHarvestedData()
{
return asmData;
}
public ListMultimap<String, String> getReverseDependencies()
{
return reverseDependencies;
}
}
@@ -30,7 +30,8 @@ import net.minecraftforge.fml.common.Mod;
* A special event used when the {@link Mod#certificateFingerprint()} doesn't match the certificate loaded from the JAR
* file. You could use this to log a warning that the code that is running might not be yours, for example.
*/
public class FMLFingerprintViolationEvent extends FMLEvent {
public class FMLFingerprintViolationEvent extends ModLifecycleEvent
{
private final boolean isDirectory;
private final Set<String> fingerprints;
@@ -39,7 +40,7 @@ public class FMLFingerprintViolationEvent extends FMLEvent {
public FMLFingerprintViolationEvent(boolean isDirectory, File source, ImmutableSet<String> fingerprints, String expectedFingerprint)
{
super();
super(null);
this.isDirectory = isDirectory;
this.source = source;
this.fingerprints = fingerprints;
@@ -19,7 +19,7 @@
package net.minecraftforge.fml.common.event;
import net.minecraftforge.fml.common.LoaderState.ModState;
import net.minecraftforge.fml.ModContainer;
/**
* Called after {@link FMLPreInitializationEvent} and before {@link FMLPostInitializationEvent} during mod
@@ -34,18 +34,11 @@ import net.minecraftforge.fml.common.LoaderState.ModState;
* @see net.minecraftforge.fml.common.Mod.EventHandler for how to subscribe to this event
* @author cpw
*/
public class FMLInitializationEvent extends FMLStateEvent
public class FMLInitializationEvent extends ModLifecycleEvent
{
public FMLInitializationEvent(Object... data)
public FMLInitializationEvent(final ModContainer container)
{
super(data);
super(container);
}
@Override
public ModState getModState()
{
return ModState.INITIALIZED;
}
}
@@ -24,11 +24,13 @@ import java.util.Optional;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.ModThreadContext;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.LoaderState;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.Mod.Instance;
import com.google.common.collect.ArrayListMultimap;
@@ -54,9 +56,15 @@ public class FMLInterModComms {
* @see net.minecraftforge.fml.common.Mod.EventHandler for how to subscribe to this event
* @author cpw
*/
public static class IMCEvent extends FMLEvent {
public static class IMCEvent extends ModLifecycleEvent
{
private ModContainer activeContainer;
public IMCEvent()
{
super(activeContainer);
}
@Override
public void applyModContainer(ModContainer activeContainer)
{
@@ -371,27 +379,19 @@ public class FMLInterModComms {
private static boolean enqueueStartupMessage(String modTarget, IMCMessage message)
{
if (Loader.instance().activeModContainer() == null)
if (ModThreadContext.get().getCurrentContainer() == null)
{
return false;
}
enqueueMessage(Loader.instance().activeModContainer(), modTarget, message);
return Loader.isModLoaded(modTarget) && !Loader.instance().hasReachedState(LoaderState.POSTINITIALIZATION);
enqueueMessage(ModThreadContext.get().getCurrentContainer(), modTarget, message);
return ModList.get().isLoaded(modTarget);
}
private static void enqueueMessage(Object sourceMod, String modTarget, IMCMessage message)
private static void enqueueMessage(ModContainer sourceMod, String modTarget, IMCMessage message)
{
ModContainer mc;
if (sourceMod instanceof ModContainer) {
mc = (ModContainer) sourceMod;
}
else
if (ModList.get().isLoaded(modTarget))
{
mc = FMLCommonHandler.instance().findContainerFor(sourceMod);
}
if (mc != null && Loader.isModLoaded(modTarget))
{
message.setSender(mc);
message.setSender(sourceMod);
modMessages.put(modTarget, message);
}
}
@@ -19,7 +19,7 @@
package net.minecraftforge.fml.common.event;
import net.minecraftforge.fml.common.LoaderState.ModState;
import net.minecraftforge.fml.ModContainer;
/**
* This is a mostly internal event fired to mod containers that indicates that loading is complete. Mods should not
@@ -27,18 +27,10 @@ import net.minecraftforge.fml.common.LoaderState.ModState;
*
* @author cpw
*/
public class FMLLoadCompleteEvent extends FMLStateEvent
public class FMLLoadCompleteEvent extends ModLifecycleEvent
{
public FMLLoadCompleteEvent(Object... data)
public FMLLoadCompleteEvent(final ModContainer container)
{
super(data);
super(container);
}
@Override
public ModState getModState()
{
return ModState.AVAILABLE;
}
}
@@ -1,23 +0,0 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* 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 version 2.1
* of the License.
*
* 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.fml.common.event;
public class FMLModDisabledEvent extends FMLEvent {
}
@@ -42,7 +42,7 @@ import net.minecraft.util.ResourceLocation;
* @see net.minecraftforge.fml.common.Mod.EventHandler for how to subscribe to this event
* @author cpw
*/
public class FMLModIdMappingEvent extends FMLEvent
public class FMLModIdMappingEvent extends ModLifecycleEvent
{
public class ModRemapping
{
@@ -66,6 +66,7 @@ public class FMLModIdMappingEvent extends FMLEvent
public final boolean isFrozen;
public FMLModIdMappingEvent(Map<ResourceLocation, Map<ResourceLocation, Integer[]>> remaps, boolean isFrozen)
{
super(null);
this.isFrozen = isFrozen;
this.remaps = Maps.newHashMap();
remaps.forEach((name, rm) ->
@@ -19,15 +19,7 @@
package net.minecraftforge.fml.common.event;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.LoaderState.ModState;
import java.lang.reflect.Constructor;
import net.minecraftforge.fml.ModContainer;
/**
* Called after {@link FMLInitializationEvent} has been dispatched on every mod. This is the third and last
@@ -38,45 +30,10 @@ import java.lang.reflect.Constructor;
* @see net.minecraftforge.fml.common.Mod.EventHandler for how to subscribe to this event
* @author cpw
*/
public class FMLPostInitializationEvent extends FMLStateEvent
public class FMLPostInitializationEvent extends ModLifecycleEvent
{
public FMLPostInitializationEvent(Object... data)
public FMLPostInitializationEvent(final ModContainer container)
{
super(data);
}
@Override
public ModState getModState()
{
return ModState.POSTINITIALIZED;
}
/**
* Build an object depending on if a specific target mod is loaded or not.
*
* Usually would be used to access an object from the other mod.
*
* @param modId The modId I conditionally want to build an object for
* @param className The name of the class I wish to instantiate
* @return An optional containing the object if possible, or null if not
*/
public Optional<?> buildSoftDependProxy(String modId, String className, Object... arguments)
{
if (Loader.isModLoaded(modId))
{
Class<?>[] args = Arrays.stream(arguments).filter(Objects::nonNull).map(Object::getClass).toArray(Class<?>[]::new);
try
{
Class<?> clz = Class.forName(className,true,Loader.instance().getModClassLoader());
Constructor<?> ct = clz.getConstructor(args);
return Optional.of(ct.newInstance(arguments));
}
catch (Exception e)
{
FMLLog.log.info("An error occurred trying to build a soft depend proxy", e);
return Optional.empty();
}
}
return Optional.empty();
super(container);
}
}
@@ -19,21 +19,8 @@
package net.minecraftforge.fml.common.event;
import java.io.File;
import java.security.CodeSource;
import java.security.cert.Certificate;
import java.util.Properties;
import net.minecraftforge.fml.javafmlmod.FMLModContainer;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.ModMetadata;
import net.minecraftforge.fml.common.LoaderState.ModState;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable;
/**
* Called before {@link FMLInitializationEvent} during mod startup.
@@ -50,131 +37,10 @@ import javax.annotation.Nullable;
* @see net.minecraftforge.fml.common.Mod.EventHandler for how to subscribe to this event
* @author cpw
*/
public class FMLPreInitializationEvent extends FMLStateEvent
public class FMLPreInitializationEvent extends ModLifecycleEvent
{
private ModMetadata modMetadata;
private File sourceFile;
private File configurationDir;
private File suggestedConfigFile;
private ASMDataTable asmData;
private ModContainer modContainer;
public FMLPreInitializationEvent(Object... data)
public FMLPreInitializationEvent(final ModContainer container)
{
super(data);
this.asmData = (ASMDataTable)data[0];
this.configurationDir = (File)data[1];
}
@Override
public ModState getModState()
{
return ModState.PREINITIALIZED;
}
@Override
public void applyModContainer(ModContainer activeContainer)
{
this.modContainer = activeContainer;
this.modMetadata = activeContainer.getMetadata();
this.sourceFile = activeContainer.getSource();
this.suggestedConfigFile = new File(configurationDir, activeContainer.getModId()+".cfg");
}
/**
* Get the {@link File} the mod was loaded from
* @return The file the mod was loaded from
*/
public File getSourceFile()
{
return sourceFile;
}
/**
* Get the {@link ModMetadata} for this mod
* @return the mod metadata for the mod
*/
public ModMetadata getModMetadata()
{
return modMetadata;
}
/**
* Get the main configuration directory for this minecraft instance
* @return the main configuration directory
*/
public File getModConfigurationDirectory()
{
return configurationDir;
}
/**
* Get a suggested configuration file for this mod. It will be of the form &lt;modid&gt;.cfg
* @return A suggested configuration file name for this mod
*/
public File getSuggestedConfigurationFile()
{
return suggestedConfigFile;
}
/**
* Get the {@link ASMDataTable} for this instance of Minecraft. This is a special structure containing
* parsing information from FML. It can be searched for annotations parsed out by FML.
* @return
*/
public ASMDataTable getAsmData()
{
return asmData;
}
/**
* Get a version.properties file as a {@link Properties} object from the mod file.
* This can be used to load build-type information
* such as a unique version number from a properties file shipped as part of the distributable.
* @return A properties object if one exists, else null
*/
@Nullable
public Properties getVersionProperties()
{
if (this.modContainer instanceof FMLModContainer)
{
return ((FMLModContainer)this.modContainer).searchForVersionProperties();
}
return null;
}
/**
* Get a logger instance configured to write to the FML Log as a parent, identified by modid. Handy for mod logging!
*
* @return A logger
*/
public Logger getModLog()
{
return LogManager.getLogger(modContainer.getModId());
}
/**
* Retrieve the FML signing certificates, if any. Validate these against the
* published FML certificates in your mod, if you wish.
*
* Deprecated because mods should <b>NOT</b> trust this code. Rather
* they should copy this, or something like this, into their own mods.
*
* @return Certificates used to sign FML and Forge
*/
@Deprecated
public Certificate[] getFMLSigningCertificates()
{
CodeSource codeSource = getClass().getClassLoader().getParent().getClass().getProtectionDomain().getCodeSource();
Certificate[] certs = codeSource.getCertificates();
if (certs == null)
{
return new Certificate[0];
}
else
{
return certs;
}
super(container);
}
}
@@ -20,25 +20,19 @@
package net.minecraftforge.fml.common.event;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.LoaderState.ModState;
import net.minecraftforge.fml.relauncher.Side;
/**
* The parent of all mod-state changing events
*/
public abstract class FMLStateEvent extends FMLEvent
public abstract class FMLStateEvent extends ModLifecycleEvent
{
public FMLStateEvent(Object... data)
public FMLStateEvent()
{
super(null);
}
/**
* The current state of the mod
* @return The current state of the mod
*/
public abstract ModState getModState();
/**
* The side we're loading on. {@link Side#CLIENT} means we're loading in the client, {@link Side#SERVER} means
* we're loading in the dedicated server.
@@ -19,24 +19,25 @@
package net.minecraftforge.fml.common.event;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.ModContainer;
/**
* Parent type to all FML events. This is based on Guava EventBus. Event Subscription isn't using the Guava annotation
* however, it's using a custom annotation specific to FML {@link net.minecraftforge.fml.common.Mod.EventHandler}
* Parent type to all ModLifecycle events. This is based on Forge EventBus. They fire through the
* ModContainer's eventbus instance.
*/
public class FMLEvent
public class ModLifecycleEvent extends Event
{
public final String getEventType()
private final ModContainer container;
public ModLifecycleEvent(ModContainer container)
{
return getClass().getSimpleName();
this.container = container;
}
public final String description()
{
String cn = getClass().getName();
return cn.substring(cn.lastIndexOf('.')+4,cn.length()-5);
}
public void applyModContainer(ModContainer activeContainer) {
// NO OP
}
}
@@ -25,12 +25,14 @@ import io.netty.channel.embedded.EmbeddedChannel;
import java.util.Map.Entry;
import net.minecraft.network.Packet;
import net.minecraftforge.api.Side;
import net.minecraftforge.fml.ModThreadContext;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.network.FMLOutboundHandler.OutboundTarget;
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher;
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.javafmlmod.ModLoadingContext;
import javax.annotation.Nullable;
@@ -44,7 +46,7 @@ import javax.annotation.Nullable;
public class FMLEmbeddedChannel extends EmbeddedChannel {
public FMLEmbeddedChannel(String channelName, Side source, ChannelHandler... handlers)
{
this(Loader.instance().activeModContainer(), channelName, source, handlers);
this(ModThreadContext.get().getCurrentContainer(), channelName, source, handlers);
}
public FMLEmbeddedChannel(ModContainer container, String channelName, Side source, ChannelHandler... handlers)
{
@@ -35,16 +35,16 @@ import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.Container;
import net.minecraft.network.INetHandler;
import net.minecraft.world.World;
import net.minecraftforge.api.Side;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import net.minecraftforge.fml.common.network.FMLOutboundHandler.OutboundTarget;
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher;
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
import net.minecraftforge.fml.common.network.internal.NetworkModHolder;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraftforge.fml.relauncher.Side;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
@@ -311,7 +311,7 @@ public enum NetworkRegistry
{
return registry.values().stream()
.filter(mod -> !mod.acceptsVanilla(from))
.map(mod -> mod.getContainer().getName())
.map(mod -> mod.getContainer().getModId())
.sorted()
.collect(Collectors.toList());
}
@@ -338,6 +338,7 @@ public enum NetworkRegistry
*/
public void fireNetworkHandshake(NetworkDispatcher networkDispatcher, Side origin)
{
/*
NetworkHandshakeEstablished handshake = new NetworkHandshakeEstablished(networkDispatcher, networkDispatcher.getNetHandler(), origin);
for (FMLEmbeddedChannel channel : channels.get(origin).values())
{
@@ -345,6 +346,7 @@ public enum NetworkRegistry
channel.attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(networkDispatcher);
channel.pipeline().fireUserEventTriggered(handshake);
}
*/
}
public void cleanAttributes()
@@ -17,6 +17,25 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@Override
public void update() {
// This method is called every tick (20 times per second normally)
if (world.isRemote) {
// We only do something on the client so we don't have to bother about client-server communication.
// The effect that we want to have (blinking the block) is client-side as well.
updateCounter();
counter -= lastCount * 3;
if (counter <= 0) {
lit = !lit;
counter = 400; // This is 20 seconds. Rate increases if more mods are near
world.markBlockRangeForRenderUpdate(getPos(), getPos());
}
}
}
private void updateCounter() {
package net.minecraftforge.fml.common.network.handshake;
import io.netty.channel.ChannelHandlerContext;
@@ -32,7 +32,7 @@ import java.util.Set;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.network.ByteBufUtils;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
@@ -33,7 +33,7 @@ import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.internal.FMLMessage.EntityMessage;
import net.minecraftforge.fml.common.registry.EntityRegistry;
@@ -31,7 +31,7 @@ import net.minecraft.entity.EntityLivingBase;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.network.ByteBufUtils;
import net.minecraftforge.fml.common.registry.EntityRegistry.EntityRegistration;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
@@ -42,7 +42,7 @@ import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLContainer;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.network.FMLEmbeddedChannel;
import net.minecraftforge.fml.common.network.FMLOutboundHandler;
import net.minecraftforge.fml.common.network.NetworkRegistry;
@@ -23,15 +23,15 @@ import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import net.minecraftforge.api.Side;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
import net.minecraftforge.fml.common.network.NetworkCheckHandler;
import net.minecraftforge.fml.common.versioning.DefaultArtifactVersion;
import net.minecraftforge.fml.common.versioning.InvalidVersionSpecificationException;
import net.minecraftforge.fml.common.versioning.VersionRange;
import net.minecraftforge.fml.relauncher.Side;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
@@ -22,7 +22,7 @@ package net.minecraftforge.fml.common.network.simpleimpl;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.network.INetHandler;
import net.minecraft.network.NetHandlerPlayServer;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.api.Side;
/**
* Context for the {@link IMessageHandler}
@@ -19,13 +19,13 @@
package net.minecraftforge.fml.common.network.simpleimpl;
import net.minecraftforge.api.Side;
import org.apache.logging.log4j.Level;
import net.minecraft.network.INetHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.network.FMLOutboundHandler;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.relauncher.Side;
import com.google.common.base.Preconditions;
@@ -33,13 +33,13 @@ import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.INetHandler;
import net.minecraft.network.Packet;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.api.Side;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.network.FMLEmbeddedChannel;
import net.minecraftforge.fml.common.network.FMLOutboundHandler;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.NetworkRegistry.TargetPoint;
import net.minecraftforge.fml.relauncher.Side;
/**
* This class is a simplified netty wrapper for those not wishing to deal with the full power of netty.
@@ -30,7 +30,7 @@ import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import java.lang.reflect.Constructor;
@@ -32,7 +32,7 @@ import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biome.SpawnListEntry;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.network.internal.FMLMessage.EntitySpawnMessage;
import java.util.function.Function;
@@ -29,7 +29,7 @@ import net.minecraftforge.fml.common.DummyModContainer;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModAPIManager;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.toposort.TopologicalSort.DirectedGraph;
import net.minecraftforge.fml.common.versioning.ArtifactVersion;
@@ -25,7 +25,7 @@ import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.fml.client.GuiSortingProblem;
import net.minecraftforge.fml.client.IDisplayableError;
import net.minecraftforge.fml.common.EnhancedRuntimeException;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@@ -19,6 +19,10 @@
package net.minecraftforge.fml.common.toposort;
import com.google.common.collect.Sets;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.util.StringBuilderFormattable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -176,7 +180,7 @@ public class TopologicalSort
return;
}
throw new TopoSortException(node, sortedResult, visitedNodes, expandedNodes);
throw new TopoSortException(new TopoSortException.TopoSortExceptionData<>(node, sortedResult, visitedNodes, expandedNodes));
}
// Visit this node
@@ -194,38 +198,68 @@ public class TopologicalSort
expandedNodes.add(node);
}
static class TopoSortException extends RuntimeException {
private final Object node;
private final List<?> sortedResult;
private final Set<?> visitedNodes;
private final Set<?> expandedNodes;
public static class TopoSortException extends RuntimeException {
private final TopoSortExceptionData<?> topoSortData;
public TopoSortException(Object node, List<?> sortedResult, Set<?> visitedNodes, Set<?> expandedNodes)
public static class TopoSortExceptionData<T> implements Message, StringBuilderFormattable
{
this.node = node;
this.sortedResult = sortedResult;
this.visitedNodes = visitedNodes;
this.expandedNodes = expandedNodes;
private final List<T> sortedResult;
private final Set<T> visitedNodes;
private final Set<T> expandedNodes;
private final T node;
TopoSortExceptionData(T node, List<T> sortedResult, Set<T> visitedNodes, Set<T> expandedNodes)
{
this.node = node;
this.sortedResult = sortedResult;
this.visitedNodes = visitedNodes;
this.expandedNodes = expandedNodes;
}
@Override
public String getFormattedMessage()
{
return "";
}
@Override
public String getFormat()
{
return "";
}
@Override
public Object[] getParameters()
{
return new Object[0];
}
@Override
public Throwable getThrowable()
{
return null;
}
@Override
public void formatTo(StringBuilder buffer)
{
buffer.append("Mod Sorting failed.\n");
buffer.append("Visiting node {}\n").append(String.valueOf(node));
buffer.append("Current sorted list : {}\n").append(String.valueOf(sortedResult));
buffer.append("Visited set for this node : {}\n").append(String.valueOf(visitedNodes));
buffer.append("Explored node set : {}\n").append(expandedNodes);
buffer.append("Likely cycle is in : {}\n").append(Sets.difference(visitedNodes, expandedNodes));
}
}
public Object getNode()
public <T> TopoSortException(TopoSortExceptionData<T> data)
{
return node;
this.topoSortData = data;
}
public List<?> getSortedResult()
{
return sortedResult;
}
public Set<?> getVisitedNodes()
{
return visitedNodes;
}
public Set<?> getExpandedNodes()
{
return expandedNodes;
@SuppressWarnings("unchecked")
public <T> TopoSortExceptionData<T> getData() {
return (TopoSortExceptionData<T>)this.topoSortData;
}
}
}
@@ -19,23 +19,28 @@
package net.minecraftforge.fml.javafmlmod;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.language.IModLanguageProvider;
import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.language.ModFileScanData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.objectweb.asm.Type;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import static net.minecraftforge.fml.Logging.LOADING;
import static net.minecraftforge.fml.Logging.SCAN;
import static net.minecraftforge.fml.Logging.fmlLog;
public class FMLJavaModLanguageProvider implements IModLanguageProvider
{
private static class FMLModTarget implements IModLanguageProvider.IModLanguageLoader {
private static final Logger LOGGER = LogManager.getLogger("FML");
private final String className;
private final String modId;
@@ -50,10 +55,21 @@ public class FMLJavaModLanguageProvider implements IModLanguageProvider
return modId;
}
@SuppressWarnings("unchecked")
@Override
public ModContainer loadMod(final IModInfo info, final ClassLoader modClassLoader, final ModFileScanData modFileScanResults)
public <T> T loadMod(final IModInfo info, final ClassLoader modClassLoader, final ModFileScanData modFileScanResults)
{
return new FMLModContainer(info, className, modClassLoader, modFileScanResults);
try
{
final Constructor<?> constructor = Class.forName("net.minecraftforge.fml.javafmlmod.FMLModContainer", true, Thread.currentThread().getContextClassLoader()).
getConstructor(IModInfo.class, String.class, ClassLoader.class, ModFileScanData.class);
return (T)constructor.newInstance(info, className, modClassLoader, modFileScanResults);
}
catch (NoSuchMethodException | ClassNotFoundException | InstantiationException | IllegalAccessException | InvocationTargetException e)
{
LOGGER.error(LOADING,"Unable to load FMLModContainer, wut?", e);
throw new RuntimeException(e);
}
}
}
@@ -71,7 +87,7 @@ public class FMLJavaModLanguageProvider implements IModLanguageProvider
final Map<String, FMLModTarget> modTargetMap = scanResult.getAnnotations().stream()
.filter(ad -> ad.getAnnotationType().equals(MODANNOTATION))
.peek(ad -> fmlLog.debug(SCAN, "Found @Mod class {} with id {}", ad.getClassType().getClassName(), ad.getAnnotationData().get("modid")))
.map(ad -> new FMLModTarget(ad.getClassType().getClassName(), (String)ad.getAnnotationData().get("modid")))
.map(ad -> new FMLModTarget(ad.getClassType().getClassName(), (String)ad.getAnnotationData().get("value")))
.collect(Collectors.toMap(FMLModTarget::getModId, Function.identity()));
scanResult.addLanguageLoader(modTargetMap);
};
@@ -18,26 +18,22 @@
*/
package net.minecraftforge.fml.javafmlmod;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Objects;
import net.minecraftforge.eventbus.EventBusErrorMessage;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.IEventListener;
import net.minecraftforge.fml.LifecycleEventProvider;
import net.minecraftforge.fml.loading.ModLoadingStage;
import net.minecraftforge.fml.common.Mod.Instance;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.common.event.ModLifecycleEvent;
import net.minecraftforge.fml.AutomaticEventSubscriber;
import net.minecraftforge.fml.ModLoadingStage;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.language.ModFileScanData;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.objectweb.asm.Type;
import java.util.function.Consumer;
import static net.minecraftforge.fml.Logging.LOADING;
@@ -45,6 +41,7 @@ public class FMLModContainer extends ModContainer
{
private static final Logger LOGGER = LogManager.getLogger("FML");
private final ModFileScanData scanResults;
private final IEventBus eventBus;
private Object modInstance;
private final Class<?> modClass;
@@ -52,43 +49,65 @@ public class FMLModContainer extends ModContainer
{
super(info);
this.scanResults = modFileScanResults;
triggerMap.put(ModLoadingStage.BEGIN, this::constructMod);
triggerMap.put(ModLoadingStage.PREINIT, this::preinitMod);
triggerMap.put(ModLoadingStage.BEGIN, dummy().andThen(this::beforeEvent).andThen(this::constructMod).andThen(this::afterEvent));
triggerMap.put(ModLoadingStage.CONSTRUCT, dummy().andThen(this::beforeEvent).andThen(this::preinitMod).andThen(this::fireEvent).andThen(this::afterEvent));
triggerMap.put(ModLoadingStage.PREINIT, dummy().andThen(this::beforeEvent).andThen(this::initMod).andThen(this::fireEvent).andThen(this::afterEvent));
this.eventBus = IEventBus.create(this::onEventFailed);
try
{
modClass = Class.forName(className, true, modClassLoader);
LOGGER.error(LOADING,"Loaded modclass {} with {}", modClass.getName(), modClass.getClassLoader());
}
catch (ClassNotFoundException e)
catch (Throwable e)
{
LOGGER.error(LOADING, "Failed to load class {}", className, e);
throw new RuntimeException(e);
}
}
private void preinitMod(LifecycleEventProvider.LifecycleEvent lifecycleEvent)
private void initMod(LifecycleEventProvider.LifecycleEvent lifecycleEvent)
{
List<Pair<String, String>> instanceFields = scanResults.getAnnotations().stream().
filter(a -> Objects.equals(a.getAnnotationType(), Type.getType(Instance.class)) &&
Objects.equals(a.getClassType(), Type.getType(modClass))).
map(a->Pair.of(a.getMemberName(), (String)a.getAnnotationData().get("value"))).
collect(Collectors.toList());
}
instanceFields.forEach(p->{
try
{
final Field field = modClass.getDeclaredField(p.getLeft());
field.setAccessible(true);
field.set(modInstance, FMLLoader.getModLoader().getModList().getModObjectById(p.getRight()).get());
}
catch (NoSuchFieldException | IllegalAccessException e)
{
LOGGER.error(LOADING, "Unable to set field {} to mod with ID {}", p.getLeft(), p.getRight(), e);
}
});
private Consumer<LifecycleEventProvider.LifecycleEvent> dummy() { return (s) -> {}; }
private void onEventFailed(IEventBus iEventBus, Event event, IEventListener[] iEventListeners, int i, Throwable throwable)
{
LOGGER.error(new EventBusErrorMessage(event, i, iEventListeners, throwable));
}
private void beforeEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent) {
ModLoadingContext.get().activeContainer = this;
}
private void fireEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent) {
final ModLifecycleEvent event = lifecycleEvent.buildModEvent(this);
LOGGER.debug(LOADING, "Firing event {} for modid {}", event, this.getModId());
try
{
eventBus.post(event);
LOGGER.debug(LOADING, "Fired event {} for modid {}", event, this.getModId());
}
catch (Throwable e)
{
LOGGER.error(LOADING,"Caught exception during event {} dispatch for modid {}", event, this.getModId(), e);
modLoadingStage = ModLoadingStage.ERROR;
modLoadingError.add(e);
}
}
private void afterEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent) {
ModLoadingContext.get().activeContainer = null;
if (getCurrentState() == ModLoadingStage.ERROR) {
LOGGER.error(LOADING,"An error occurred while dispatching event {} to {}", lifecycleEvent.fromStage(), getModId());
}
}
private void preinitMod(LifecycleEventProvider.LifecycleEvent lifecycleEvent)
{
AutomaticEventSubscriber.inject(this, this.scanResults, this.modClass.getClassLoader());
}
private void constructMod(LifecycleEventProvider.LifecycleEvent event)
@@ -99,10 +118,11 @@ public class FMLModContainer extends ModContainer
this.modInstance = modClass.newInstance();
LOGGER.debug(LOADING, "Loaded mod instance {} of type {}", getModId(), modClass.getName());
}
catch (InstantiationException | IllegalAccessException e)
catch (Throwable e)
{
LOGGER.error("Failed to create mod instance. ModID: {}, class {}", getModId(), modClass.getName(), e);
throw new RuntimeException("Failed to create mod instance", e);
LOGGER.error(LOADING,"Failed to create mod instance. ModID: {}, class {}", getModId(), modClass.getName(), e);
modLoadingStage = ModLoadingStage.ERROR;
modLoadingError.add(e);
}
}
@@ -118,9 +138,8 @@ public class FMLModContainer extends ModContainer
return modInstance;
}
@Override
public <T> T getCustomExtension(final String name)
public IEventBus getEventBus()
{
return ((Function<String,T>)modInstance).apply(name);
return this.eventBus;
}
}
@@ -17,9 +17,27 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.loading;
package net.minecraftforge.fml.javafmlmod;
public enum ModLoadingStage
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.language.ExtensionPoint;
import java.util.function.Supplier;
public class ModLoadingContext
{
ERROR, BEGIN, CONSTRUCT, PREINIT, INIT, POSTINIT, COMPLETE
private static ThreadLocal<ModLoadingContext> context = ThreadLocal.withInitial(ModLoadingContext::new);
FMLModContainer activeContainer;
public static ModLoadingContext get() {
return context.get();
}
public <T> void registerExtensionPoint(ExtensionPoint<T> point, Supplier<T> extension) {
activeContainer.registerExtensionPoint(point, extension);
}
public IEventBus getModEventBus()
{
return activeContainer.getEventBus();
}
}
@@ -17,14 +17,17 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.common.event;
package net.minecraftforge.fml.language;
/**
* Internal only event, used to begin the lifecycle of loading mods.
*
* @author cpw
*/
public class FMLLoadEvent
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.IResourcePack;
import java.util.function.BiFunction;
import java.util.function.Function;
public class ExtensionPoint<T>
{
public static final ExtensionPoint<BiFunction<Minecraft, GuiScreen, GuiScreen>> GUIFACTORY = new ExtensionPoint<>();
public static final ExtensionPoint<Function<Minecraft, IResourcePack>> RESOURCEPACK = new ExtensionPoint<>();
}
@@ -107,5 +107,10 @@ public interface IModInfo
{
this.owner = owner;
}
public IModInfo getOwner()
{
return owner;
}
}
}
@@ -22,7 +22,7 @@ package net.minecraftforge.fml.language;
import java.util.function.Consumer;
/**
* Loaded as a ServiceLoader, from the classpath. Extensions are loaded from
* Loaded as a ServiceLoader, from the classpath. ExtensionPoint are loaded from
* the mods directory, with the FMLType META-INF of LANGPROVIDER.
*
* Version data is read from the manifest's implementation version.
@@ -34,6 +34,6 @@ public interface IModLanguageProvider
Consumer<ModFileScanData> getFileVisitor();
interface IModLanguageLoader {
ModContainer loadMod(IModInfo info, ClassLoader modClassLoader, ModFileScanData modFileScanResults);
<T> T loadMod(IModInfo info, ClassLoader modClassLoader, ModFileScanData modFileScanResults);
}
}
@@ -0,0 +1,64 @@
/*
* Minecraft Forge
* Copyright (c) 2018.
*
* 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 version 2.1
* of the License.
*
* 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.fml.loading;
import com.electronwill.nightconfig.core.path.PathConfig;
import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
public class DefaultModInfos
{
static {
PathConfig minecraftmod;
PathConfig forgemod;
try
{
minecraftmod = PathConfig.of(Paths.get(DefaultModInfos.class.getClassLoader().getResource("minecraftmod.toml").toURI()));
forgemod = PathConfig.of(Paths.get(DefaultModInfos.class.getClassLoader().getResource("forgemod.toml").toURI()));
minecraftmod.load();
forgemod.load();
}
catch (URISyntaxException | NullPointerException e)
{
throw new RuntimeException("Missing toml configs for minecraft and forge!", e);
}
minecraftModInfo = new ModInfo(null, minecraftmod);
forgeModInfo = new ModInfo(null, forgemod);
}
public static final IModInfo minecraftModInfo;
private static final IModInfo forgeModInfo;
// no construction
private DefaultModInfos() {}
public static List<IModInfo> getModInfos()
{
return Arrays.asList(minecraftModInfo, forgeModInfo);
}
}
@@ -24,6 +24,7 @@ import cpw.mods.modlauncher.api.ILaunchHandlerService;
import cpw.mods.modlauncher.api.ITransformingClassLoader;
import net.minecraftforge.api.Side;
import java.lang.reflect.Field;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -72,6 +73,10 @@ public class FMLDevClientLaunchProvider extends FMLCommonLaunchHandler implement
fmlLog.debug(CORE, "Launching minecraft in {} with arguments {}", launchClassLoader, arguments);
super.beforeStart(launchClassLoader);
launchClassLoader.addTargetPackageFilter(cn -> SKIPPACKAGES.stream().noneMatch(cn::startsWith));
Field scl = ClassLoader.class.getDeclaredField("scl"); // Get system class loader
scl.setAccessible(true); // Set accessible
scl.set(null, launchClassLoader.getInstance()); // Update it to your class loader
Thread.currentThread().setContextClassLoader(launchClassLoader.getInstance());
Class.forName("net.minecraft.client.main.Main", true, launchClassLoader.getInstance()).getMethod("main", String[].class).invoke(null, (Object)arguments);
return null;
};
@@ -27,14 +27,11 @@ import cpw.mods.modlauncher.api.IncompatibleEnvironmentException;
import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
import net.minecraftforge.api.Side;
import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.fml.common.FMLPaths;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.loading.moddiscovery.BackgroundScanHandler;
import net.minecraftforge.fml.loading.moddiscovery.ModDiscoverer;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.forgespi.ICoreModProvider;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
@@ -57,9 +54,8 @@ public class FMLLoader
private static ILaunchPluginService eventBus;
private static LanguageLoadingProvider languageLoadingProvider;
private static Side side;
private static ModList modList;
private static LoadingModList loadingModList;
private static ClassLoader launchClassLoader;
private static ModLoader modLoader;
static void onInitialLoad(IEnvironment environment, Set<String> otherServices) throws IncompatibleEnvironmentException
{
@@ -134,7 +130,7 @@ public class FMLLoader
fmlLog.debug(SCAN,"Scanning for Mod Locators");
modDiscoverer = new ModDiscoverer();
final BackgroundScanHandler backgroundScanHandler = modDiscoverer.discoverMods();
modList = backgroundScanHandler.getModList();
loadingModList = backgroundScanHandler.getLoadingModList();
}
public static ICoreModProvider getCoreModProvider() {
@@ -177,12 +173,18 @@ public class FMLLoader
public static void beforeStart(ITransformingClassLoader launchClassLoader)
{
modLoader = new ModLoader(launchClassLoader.getInstance(), modList);
modLoader.classloadModFiles();
FMLLoader.launchClassLoader = launchClassLoader.getInstance();
}
public static ModLoader getModLoader()
public static LoadingModList getLoadingModList()
{
return modLoader;
return loadingModList;
}
public static ClassLoader getLaunchClassLoader()
{
return launchClassLoader;
}
}
@@ -19,13 +19,16 @@
package net.minecraftforge.fml.loading;
import com.google.common.collect.Streams;
import net.minecraftforge.fml.LifecycleEventProvider;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModLoadingStage;
import net.minecraftforge.fml.loading.moddiscovery.BackgroundScanHandler;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
@@ -37,9 +40,9 @@ import java.util.stream.Collectors;
/**
* Master list of all mods
*/
public class ModList
public class LoadingModList
{
private static ModList INSTANCE;
private static LoadingModList INSTANCE;
private final List<ModFileInfo> modFiles;
private final List<ModInfo> sortedList;
private final Map<String, ModFileInfo> fileById;
@@ -47,22 +50,24 @@ public class ModList
private List<ModContainer> mods;
private Map<String, ModContainer> indexedMods;
private ModList(final List<ModFile> modFiles, final List<ModInfo> sortedList)
private LoadingModList(final List<ModFile> modFiles, final List<ModInfo> sortedList)
{
this.modFiles = modFiles.stream().map(ModFile::getModFileInfo).map(ModFileInfo.class::cast).collect(Collectors.toList());
this.sortedList = sortedList;
this.sortedList = Streams.concat(DefaultModInfos.getModInfos().stream(), sortedList.stream()).
map(ModInfo.class::cast).
collect(Collectors.toList());
this.fileById = this.modFiles.stream().map(ModFileInfo::getMods).flatMap(Collection::stream).
map(ModInfo.class::cast).
collect(Collectors.toMap(ModInfo::getModId, ModInfo::getOwningFile));
}
public static ModList of(List<ModFile> modFiles, List<ModInfo> sortedList)
public static LoadingModList of(List<ModFile> modFiles, List<ModInfo> sortedList)
{
INSTANCE = new ModList(modFiles, sortedList);
INSTANCE = new LoadingModList(modFiles, sortedList);
return INSTANCE;
}
public static ModList get() {
public static LoadingModList get() {
return INSTANCE;
}
public void addCoreMods()
@@ -78,7 +83,7 @@ public class ModList
public void addForScanning(BackgroundScanHandler backgroundScanHandler)
{
this.scanner = backgroundScanHandler;
backgroundScanHandler.setModList(this);
backgroundScanHandler.setLoadingModList(this);
modFiles.stream().map(ModFileInfo::getFile).forEach(backgroundScanHandler::submitForScanning);
}
@@ -91,7 +96,7 @@ public class ModList
{
for (ModFileInfo mf : modFiles) {
final Path resource = mf.getFile().findResource(className);
if (resource != null) return resource;
if (Files.exists(resource)) return resource;
}
return null;
}
@@ -109,7 +114,7 @@ public class ModList
}
}
public void setLoadedMods(List<ModContainer> modContainers)
public void setLoadedMods(final List<ModContainer> modContainers)
{
this.mods = modContainers;
this.indexedMods = modContainers.stream().collect(Collectors.toMap(ModContainer::getModId, Function.identity()));
@@ -47,7 +47,7 @@ public class ModJarURLHandler extends URLStreamHandler
@Override
public InputStream getInputStream() throws IOException
{
return Files.newInputStream(FMLLoader.getModLoader().getModList().getModFileById(modid).getFile().findResource(modpath));
return Files.newInputStream(FMLLoader.getLoadingModList().getModFileById(modid).getFile().findResource(modpath));
}
};
}
@@ -1,60 +0,0 @@
/*
* Minecraft Forge
* Copyright (c) 2018.
*
* 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 version 2.1
* of the License.
*
* 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.fml.loading;
import net.minecraftforge.fml.LifecycleEventProvider;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import java.util.Collection;
import java.util.stream.Collectors;
public class ModLoader
{
private final ClassLoader launchClassLoader;
private final ModList modList;
private final ModLoadingClassLoader modClassLoader;
public ModLoader(final ClassLoader launchClassLoader, final ModList modList)
{
this.launchClassLoader = launchClassLoader;
this.modList = modList;
this.modClassLoader = new ModLoadingClassLoader(this, this.launchClassLoader);
}
public void classloadModFiles()
{
}
public ModList getModList()
{
return modList;
}
public void loadMods() {
modList.setLoadedMods(modList.getModFiles().stream().
map(ModFileInfo::getFile).
map(mf -> mf.buildMods(this.modClassLoader)).
flatMap(Collection::stream).collect(Collectors.toList()));
LifecycleEventProvider.LOAD.dispatch(modList);
LifecycleEventProvider.PREINIT.dispatch(modList);
}
}
@@ -19,7 +19,6 @@
package net.minecraftforge.fml.loading;
import net.minecraftforge.fml.DefaultModContainers;
import net.minecraftforge.fml.Java9BackportUtils;
import net.minecraftforge.fml.common.DuplicateModsFoundException;
import net.minecraftforge.fml.common.MissingModsException;
@@ -27,14 +26,17 @@ import net.minecraftforge.fml.common.toposort.TopologicalSort;
import net.minecraftforge.fml.common.versioning.ArtifactVersion;
import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -42,34 +44,59 @@ import static net.minecraftforge.fml.Logging.LOADING;
public class ModSorter
{
private final List<ModFile> modFiles;
private static final Logger LOGGER = LogManager.getLogger("FML");
private List<ModFile> modFiles;
private List<ModInfo> sortedList;
private Map<String, ModInfo> modIdNameLookup;
public ModSorter(final List<ModFile> modFiles)
private ModSorter(final List<ModFile> modFiles)
{
this.modFiles = modFiles;
}
public static ModList sort(List<ModFile> mods)
public static LoadingModList sort(List<ModFile> mods)
{
final ModSorter ms = new ModSorter(mods);
ms.buildUniqueList();
ms.verifyDependencyVersions();
ms.sort();
return ModList.of(ms.modFiles, ms.sortedList);
return LoadingModList.of(ms.modFiles, ms.sortedList);
}
private void sort() {
final TopologicalSort.DirectedGraph<IModInfo> topoGraph = new TopologicalSort.DirectedGraph<>();
modFiles.stream().map(ModFile::getModInfos).
flatMap(Collection::stream).forEach(topoGraph::addNode);
modFiles.stream().map(ModFile::getModInfos).
flatMap(Collection::stream).map(IModInfo::getDependencies).flatMap(Collection::stream).forEach(dep->addDependency(topoGraph, dep));
}
private void addDependency(TopologicalSort.DirectedGraph<IModInfo> topoGraph, IModInfo.ModVersion dep)
private void sort()
{
final TopologicalSort.DirectedGraph<Supplier<ModFileInfo>> topoGraph = new TopologicalSort.DirectedGraph<>();
modFiles.stream().map(ModFile::getModFileInfo).map(ModFileInfo.class::cast).forEach(mi -> topoGraph.addNode(() -> mi));
modFiles.stream().map(ModFile::getModInfos).flatMap(Collection::stream).map(IModInfo::getDependencies).flatMap(Collection::stream).
forEach(dep -> addDependency(topoGraph, dep));
final List<Supplier<ModFileInfo>> sorted;
try
{
sorted = TopologicalSort.topologicalSort(topoGraph);
}
catch (TopologicalSort.TopoSortException e)
{
TopologicalSort.TopoSortException.TopoSortExceptionData<Supplier<ModInfo>> data = e.getData();
LOGGER.error(LOADING, ()-> data);
throw e;
}
this.sortedList = sorted.stream().map(Supplier::get).map(ModFileInfo::getMods).
flatMap(Collection::stream).map(ModInfo.class::cast).collect(Collectors.toList());
this.modFiles = sorted.stream().map(Supplier::get).map(ModFileInfo::getFile).collect(Collectors.toList());
}
private void addDependency(TopologicalSort.DirectedGraph<Supplier<ModFileInfo>> topoGraph,IModInfo.ModVersion dep)
{
switch (dep.getOrdering()) {
case BEFORE:
topoGraph.addEdge(()->(ModFileInfo)dep.getOwner().getOwningFile(), ()->modIdNameLookup.get(dep.getModId()).getOwningFile());
break;
case AFTER:
topoGraph.addEdge(()->modIdNameLookup.get(dep.getModId()).getOwningFile(), ()->(ModFileInfo)dep.getOwner().getOwningFile());
break;
case NONE:
break;
}
}
private void buildUniqueList()
@@ -90,7 +117,7 @@ public class ModSorter
private void verifyDependencyVersions()
{
final Map<String, ArtifactVersion> modVersions = Stream.concat(modFiles.stream().map(ModFile::getModInfos).
flatMap(Collection::stream), DefaultModContainers.getModInfos().stream()).collect(Collectors.toMap(IModInfo::getModId, IModInfo::getVersion));
flatMap(Collection::stream), DefaultModInfos.getModInfos().stream()).collect(Collectors.toMap(IModInfo::getModId, IModInfo::getVersion));
final Map<IModInfo, List<IModInfo.ModVersion>> modVersionDependencies = modFiles.stream().
map(ModFile::getModInfos).flatMap(Collection::stream).
collect(Collectors.groupingBy(Function.identity(), Java9BackportUtils.flatMapping(e -> e.getDependencies().stream(), Collectors.toList())));
@@ -20,7 +20,7 @@
package net.minecraftforge.fml.loading.moddiscovery;
import net.minecraftforge.fml.language.ModFileScanData;
import net.minecraftforge.fml.loading.ModList;
import net.minecraftforge.fml.loading.LoadingModList;
import java.util.ArrayList;
import java.util.List;
@@ -38,7 +38,7 @@ public class BackgroundScanHandler
private final List<ModFile> pendingFiles;
private final List<ModFile> scannedFiles;
private final List<ModFile> allFiles;
private ModList modList;
private LoadingModList loadingModList;
public BackgroundScanHandler() {
modContentScanner = Executors.newSingleThreadExecutor(r -> {
@@ -86,13 +86,13 @@ public class BackgroundScanHandler
return allFiles;
}
public void setModList(ModList modList)
public void setLoadingModList(LoadingModList loadingModList)
{
this.modList = modList;
this.loadingModList = loadingModList;
}
public ModList getModList()
public LoadingModList getLoadingModList()
{
return modList;
return loadingModList;
}
}
@@ -21,7 +21,7 @@ package net.minecraftforge.fml.loading.moddiscovery;
import cpw.mods.modlauncher.ServiceLoaderStreamUtils;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.loading.ModList;
import net.minecraftforge.fml.loading.LoadingModList;
import net.minecraftforge.fml.loading.ModSorter;
import java.util.Collection;
@@ -70,10 +70,10 @@ public class ModDiscoverer {
}
}
fmlLog.debug(SCAN,"Found {} mod files with {} mods", mods::size, ()->mods.stream().mapToInt(mf -> mf.getModInfos().size()).sum());
final ModList modList = ModSorter.sort(mods);
modList.addCoreMods();
modList.addAccessTransformers();
modList.addForScanning(backgroundScanHandler);
final LoadingModList loadingModList = ModSorter.sort(mods);
loadingModList.addCoreMods();
loadingModList.addAccessTransformers();
loadingModList.addForScanning(backgroundScanHandler);
return backgroundScanHandler;
}
}
@@ -20,13 +20,11 @@
package net.minecraftforge.fml.loading.moddiscovery;
import com.google.common.collect.ImmutableMap;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.language.IModFileInfo;
import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.language.ModFileScanData;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.language.IModLanguageProvider;
import net.minecraftforge.fml.loading.ModLoadingClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -37,11 +35,9 @@ import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
import static net.minecraftforge.fml.Logging.LOADING;
import static net.minecraftforge.fml.Logging.SCAN;
@@ -74,12 +70,6 @@ public class ModFile
return locator.findPath(this, className);
}
public List<ModContainer> buildMods(ModLoadingClassLoader modClassLoader)
{
return getScanResult().getTargets().entrySet().stream().
map(e->e.getValue().loadMod(this.modInfoMap.get(e.getKey()), modClassLoader, getScanResult())).collect(Collectors.toList());
}
public enum Type {
MOD, LIBRARY, LANGPROVIDER
}
@@ -88,7 +78,6 @@ public class ModFile
private final Manifest manifest;
private final IModLocator locator;
private IModFileInfo modFileInfo;
private Map<String, IModInfo> modInfoMap;
private ModFileScanData fileModFileScanData;
private CompletableFuture<ModFileScanData> futureScanResult;
private List<CoreModFile> coreMods;
@@ -129,7 +118,6 @@ public class ModFile
this.modFileInfo = ModFileParser.readModList(this);
if (this.modFileInfo == null) return false;
fmlLog.debug(LOADING,"Loading mod file {} with language {}", this.getFilePath(), this.modFileInfo.getModLoader());
this.modInfoMap = this.getModInfos().stream().collect(Collectors.toMap(IModInfo::getModId, Function.identity()));
this.coreMods = ModFileParser.getCoreMods(this);
this.coreMods.forEach(mi-> fmlLog.debug(LOADING,"Found coremod {}", mi.getPath()));
this.accessTransformer = locator.findPath(this, "META-INF", "accesstransformer.cfg");
@@ -42,7 +42,7 @@ import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.IFMLSidedHandler;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.StartupQuery;
import net.minecraftforge.fml.common.network.FMLNetworkEvent;
import net.minecraftforge.fml.relauncher.Side;
@@ -30,7 +30,7 @@ import java.util.Set;
import net.minecraft.block.BlockPrismarine;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
@@ -28,7 +28,7 @@ import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.event.entity.player.ItemTooltipEvent;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.language.ModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.Side;
@Mod(modid = "forgemodnametooltip", name = "ForgeModNameTooltip", version = "1.0", clientSideOnly = true)