diff --git a/forge/src/accessors/java/org/spongepowered/forge/accessor/fml/ModListAccessor.java b/forge/src/accessors/java/org/spongepowered/forge/accessor/fml/ModListAccessor.java deleted file mode 100644 index 2f223b54bba..00000000000 --- a/forge/src/accessors/java/org/spongepowered/forge/accessor/fml/ModListAccessor.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.accessor.fml; - -import net.minecraftforge.fml.ModContainer; -import net.minecraftforge.fml.ModList; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.List; - -@Mixin(value = ModList.class, remap = false) -public interface ModListAccessor { - - @Accessor("mods") List accessor$mods(); -} diff --git a/forge/src/accessors/java/org/spongepowered/forge/accessor/fml/javafmlmod/FMLModContainerAccessor.java b/forge/src/accessors/java/org/spongepowered/forge/accessor/fml/javafmlmod/FMLModContainerAccessor.java deleted file mode 100644 index ed30fa282ac..00000000000 --- a/forge/src/accessors/java/org/spongepowered/forge/accessor/fml/javafmlmod/FMLModContainerAccessor.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.accessor.fml.javafmlmod; - -import net.minecraftforge.fml.javafmlmod.FMLModContainer; -import net.minecraftforge.forgespi.language.ModFileScanData; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(FMLModContainer.class) -public interface FMLModContainerAccessor { - - @Accessor("scanResults") ModFileScanData accessor$scanResults(); - - @Accessor("modClass") Class accessor$modClass(); - - @Accessor("modInstance") void accessor$setModInstance(Object instance); -} diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/ModFileParsers.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/ModFileParsers.java index 8dcf8d688b0..bc87dd183bb 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/ModFileParsers.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/ModFileParsers.java @@ -27,75 +27,73 @@ import cpw.mods.jarhandling.SecureJar; import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo; -import net.minecraftforge.fml.loading.moddiscovery.NightConfigWrapper; -import net.minecraftforge.forgespi.language.IConfigurable; +import net.minecraftforge.fml.loading.moddiscovery.ModJarMetadata; import net.minecraftforge.forgespi.language.IModFileInfo; import net.minecraftforge.forgespi.locating.IModFile; import net.minecraftforge.forgespi.locating.IModLocator; import net.minecraftforge.forgespi.locating.ModFileFactory; import org.spongepowered.common.applaunch.AppLaunch; +import org.spongepowered.common.applaunch.plugin.PluginPlatformConstants; import org.spongepowered.forge.applaunch.loading.metadata.PluginFileConfigurable; import org.spongepowered.plugin.metadata.builtin.MetadataContainer; import org.spongepowered.plugin.metadata.builtin.MetadataParser; import java.io.Reader; import java.lang.reflect.Constructor; -import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.util.List; public final class ModFileParsers { - - private static Constructor modFileInfoConstructor; - private static Field modFileInfoField; + private static Constructor modJarMetadataConstructor; static { try { - ModFileParsers.modFileInfoConstructor = ModFileInfo.class.getDeclaredConstructor(ModFile.class, IConfigurable.class); - ModFileParsers.modFileInfoField = NightConfigWrapper.class.getDeclaredField("file"); + ModFileParsers.modJarMetadataConstructor = ModJarMetadata.class.getDeclaredConstructor(); + ModFileParsers.modJarMetadataConstructor.setAccessible(true); } catch (final Exception e) { throw new RuntimeException(e); } } - public static IModFileInfo pluginMetadataParser(final String fileName, final IModFile iModFile) { - final ModFile modFile = (ModFile)iModFile; + public static IModFileInfo parsePluginMetadata(final IModFile iModFile) { + final ModFile modFile = (ModFile) iModFile; AppLaunch.logger().debug("Considering plugin file candidate {}", modFile.getFilePath()); - final Path metadataFile = modFile.findResource("META-INF/" + fileName + ".json"); + + final Path metadataFile = modFile.findResource(PluginPlatformConstants.METADATA_FILE_LOCATION); if (Files.notExists(metadataFile)) { AppLaunch.logger().debug("Plugin file '{}' is missing a 'sponge_plugins.json' metadata file in META-INF", modFile); return null; } + try { final MetadataContainer container; try (final Reader reader = Files.newBufferedReader(metadataFile, StandardCharsets.UTF_8)) { container = MetadataParser.read(reader); } - final PluginFileConfigurable configurable = new PluginFileConfigurable(container); - return ModFileParsers.generateModFileMetadata(modFile, configurable); + final PluginFileConfigurable config = new PluginFileConfigurable(container); + return new ModFileInfo(modFile, config, List.of()); } catch (final Exception e) { AppLaunch.logger().warn("Could not read metadata for plugin file '{}'", modFile, e); return null; } } - private static ModFileInfo generateModFileMetadata(final ModFile file, final IConfigurable configurable) throws Exception { - ModFileParsers.modFileInfoConstructor.setAccessible(true); - final ModFileInfo modFileInfo = ModFileParsers.modFileInfoConstructor.newInstance(file, configurable); - ModFileParsers.modFileInfoConstructor.setAccessible(false); - if (configurable instanceof NightConfigWrapper) { - ModFileParsers.modFileInfoField.setAccessible(true); - ModFileParsers.modFileInfoField.set(configurable, modFileInfo); - ModFileParsers.modFileInfoField.setAccessible(false); + private static ModJarMetadata newModJarMetadata() { + try { + return modJarMetadataConstructor.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); } - - return modFileInfo; } - public static ModFile newPluginInstance(final SecureJar jar, final IModLocator locator, final String fileName) { - return (ModFile) ModFileFactory.FACTORY.build(jar, locator, file -> ModFileParsers.pluginMetadataParser(fileName, file)); + public static ModFile newPluginInstance(final IModLocator locator, final Path... path) { + ModJarMetadata mjm = newModJarMetadata(); + ModFile modFile = (ModFile) ModFileFactory.FACTORY.build(SecureJar.from(jar -> mjm, path), locator, ModFileParsers::parsePluginMetadata); + mjm.setModFile(modFile); + return modFile; } private ModFileParsers() { diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/ClasspathPluginLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/ClasspathPluginLocator.java index 5c505a10024..36b4c6af327 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/ClasspathPluginLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/ClasspathPluginLocator.java @@ -24,7 +24,6 @@ */ package org.spongepowered.forge.applaunch.loading.moddiscovery.locator; -import cpw.mods.jarhandling.SecureJar; import net.minecraftforge.fml.loading.ClasspathLocatorUtils; import net.minecraftforge.fml.loading.moddiscovery.AbstractJarFileModLocator; import org.apache.logging.log4j.LogManager; @@ -40,12 +39,10 @@ import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; -import java.util.function.Predicate; import java.util.stream.Stream; public final class ClasspathPluginLocator extends AbstractJarFileModLocator { private static final Logger LOGGER = LogManager.getLogger(); - private static final String PLUGINS_JSON = "META-INF/sponge_plugins.json"; private Set modCoords; @Override @@ -55,7 +52,7 @@ public Stream scanCandidates() { @Override protected ModFileOrException createMod(Path... path) { - return new ModFileOrException(ModFileParsers.newPluginInstance(SecureJar.from(path), this, PluginPlatformConstants.METADATA_FILE_NAME), null); + return new ModFileOrException(ModFileParsers.newPluginInstance(this, path), null); } @Override @@ -67,14 +64,14 @@ public String name() { public void initArguments(final Map arguments) { try { this.modCoords = new LinkedHashSet<>(); - this.locateMods(ClasspathPluginLocator.PLUGINS_JSON, "classpath_plugin", path -> true); + this.locateMods(PluginPlatformConstants.METADATA_FILE_LOCATION, "classpath_plugin"); } catch (IOException e) { ClasspathPluginLocator.LOGGER.fatal("Error trying to find resources", e); throw new RuntimeException("wha?", e); } } - private void locateMods(final String resource, final String name, final Predicate filter) throws IOException { + private void locateMods(final String resource, final String name) throws IOException { final Enumeration pluginJsons = ClassLoader.getSystemClassLoader().getResources(resource); while (pluginJsons.hasMoreElements()) { final URL url = pluginJsons.nextElement(); @@ -82,10 +79,8 @@ private void locateMods(final String resource, final String name, final Predicat if (Files.isDirectory(path)) continue; - if (filter.test(path)) { - ClasspathPluginLocator.LOGGER.debug("Found classpath plugin: {}", path); - this.modCoords.add(path); - } + ClasspathPluginLocator.LOGGER.debug("Found classpath plugin: {}", path); + this.modCoords.add(path); } } } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsFolderLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsFolderLocator.java index dc8421d72a4..e87a90cb748 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsFolderLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsFolderLocator.java @@ -24,7 +24,6 @@ */ package org.spongepowered.forge.applaunch.loading.moddiscovery.locator; -import cpw.mods.jarhandling.SecureJar; import cpw.mods.modlauncher.api.LamdbaExceptionUtils; import net.minecraftforge.fml.loading.ModDirTransformerDiscoverer; import net.minecraftforge.fml.loading.StringUtils; @@ -34,7 +33,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.common.applaunch.AppLaunch; -import org.spongepowered.common.applaunch.plugin.PluginPlatformConstants; import org.spongepowered.forge.applaunch.loading.moddiscovery.ModFileParsers; import java.nio.file.Files; @@ -65,10 +63,9 @@ public List scanMods() { private Stream scanForModsIn(final Path pluginsDirectory) { final List excluded = ModDirTransformerDiscoverer.allExcluded(); return LamdbaExceptionUtils.uncheck(() -> Files.list(pluginsDirectory)) - .filter((p) -> !excluded.contains(p)) + .filter((p) -> !excluded.contains(p) && StringUtils.toLowerCase(p.getFileName().toString()).endsWith(".jar")) .sorted(Comparator.comparing((path) -> StringUtils.toLowerCase(path.getFileName().toString()))) - .filter((p) -> StringUtils.toLowerCase(p.getFileName().toString()).endsWith(".jar")) - .map((p) -> ModFileParsers.newPluginInstance(SecureJar.from(p), this, PluginPlatformConstants.METADATA_FILE_NAME)) + .map((p) -> ModFileParsers.newPluginInstance(this, p)) .filter(ModFile::identifyMods); } diff --git a/forge/src/lang/java/org/spongepowered/forge/lang/provider/JavaPluginLanguageProvider.java b/forge/src/lang/java/org/spongepowered/forge/lang/provider/JavaPluginLanguageProvider.java index e1d6f1c7e52..5bdcef45012 100644 --- a/forge/src/lang/java/org/spongepowered/forge/lang/provider/JavaPluginLanguageProvider.java +++ b/forge/src/lang/java/org/spongepowered/forge/lang/provider/JavaPluginLanguageProvider.java @@ -82,7 +82,7 @@ private PluginTarget(final String className, final String plugin) { } @Override - public T loadMod(final IModInfo info, final ModFileScanData modFileScanData, final ModuleLayer moduleLayer) { + public T loadMod(final IModInfo info, final ModFileScanData modFileScanData, final ModuleLayer gameLayer) { // The following is adapted from FMLJavaModLanguageProvider.FMLModTarget // This language class is loaded in the system level classloader - before the game even starts @@ -93,7 +93,7 @@ public T loadMod(final IModInfo info, final ModFileScanData modFileScanData, "org.spongepowered.forge.launch.plugin.PluginModContainer", true, Thread.currentThread().getContextClassLoader()); this.logger.debug(Logging.LOADING, "Loading PluginModContainer from classloader {} - got {}", Thread.currentThread().getContextClassLoader(), pluginContainer.getClassLoader()); final Constructor constructor = pluginContainer.getConstructor(IModInfo.class, String.class, ModFileScanData.class, ModuleLayer.class); - return (T) constructor.newInstance(info, className, modFileScanData, moduleLayer); + return (T) constructor.newInstance(info, className, modFileScanData, gameLayer); } // ALL exception handling has to be done through the classloader, because we're loaded in the wrong context, so any classes we just blind load will be in the wrong // class loading context. Funky but works. diff --git a/forge/src/launch/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java b/forge/src/launch/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java index 65e6c7c9815..81d9bb066e0 100644 --- a/forge/src/launch/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java +++ b/forge/src/launch/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java @@ -24,6 +24,7 @@ */ package org.spongepowered.forge.launch.plugin; +import com.google.common.collect.MapMaker; import net.minecraftforge.fml.ModContainer; import net.minecraftforge.fml.loading.moddiscovery.ModInfo; import org.apache.logging.log4j.LogManager; @@ -36,6 +37,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -90,8 +92,9 @@ public Object instance() { return this.modContainer.getMod(); } + private static final Map containers = new MapMaker().weakKeys().makeMap(); + public static ForgePluginContainer of(final ModContainer modContainer) { - // TODO SF 1.19.4, ensure unicity by storing references in a map - return new ForgePluginContainer(modContainer); + return containers.computeIfAbsent(modContainer, ForgePluginContainer::new); } } diff --git a/forge/src/launch/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java b/forge/src/launch/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java index 25309186f92..074f2e0992e 100644 --- a/forge/src/launch/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java +++ b/forge/src/launch/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java @@ -24,13 +24,13 @@ */ package org.spongepowered.forge.launch.plugin; +import com.google.common.collect.ImmutableList; import com.google.inject.Singleton; import net.minecraftforge.fml.ModList; import org.spongepowered.common.launch.plugin.SpongePluginManager; import org.spongepowered.plugin.PluginContainer; import java.util.Collection; -import java.util.Collections; import java.util.Objects; import java.util.Optional; @@ -50,7 +50,8 @@ public Optional plugin(final String id) { @Override public Collection plugins() { - return Collections.emptyList(); // TODO SF 1.19.4, we can no longer use accessors on FML, is time for reflection? - // return Collections.unmodifiableCollection((Collection) (Object) ((ModListAccessor) ModList.get()).accessor$mods()); + final ImmutableList.Builder builder = ImmutableList.builder(); + ModList.get().forEachModInOrder(mod -> builder.add(ForgePluginContainer.of(mod))); + return builder.build(); } } diff --git a/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java b/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java index cc659c4923a..73f92ca0389 100644 --- a/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java +++ b/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java @@ -24,58 +24,106 @@ */ package org.spongepowered.forge.launch.plugin; -import static net.minecraftforge.fml.Logging.LOADING; - import com.google.inject.Injector; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.EventBusErrorMessage; +import net.minecraftforge.eventbus.api.BusBuilder; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.eventbus.api.IEventListener; import net.minecraftforge.fml.Logging; +import net.minecraftforge.fml.ModContainer; import net.minecraftforge.fml.ModLoadingException; import net.minecraftforge.fml.ModLoadingStage; +import net.minecraftforge.fml.event.IModBusEvent; import net.minecraftforge.fml.javafmlmod.AutomaticEventSubscriber; -import net.minecraftforge.fml.javafmlmod.FMLModContainer; import net.minecraftforge.forgespi.language.IModInfo; import net.minecraftforge.forgespi.language.ModFileScanData; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.common.inject.plugin.PluginModule; import org.spongepowered.common.launch.Launch; -import org.spongepowered.forge.accessor.fml.javafmlmod.FMLModContainerAccessor; import org.spongepowered.forge.launch.event.ForgeEventManager; import org.spongepowered.plugin.PluginContainer; -// If this class name changes, fix FMLModContainerMixin_Forge -public final class PluginModContainer extends FMLModContainer { +import java.util.Optional; +// Spongified FMLModContainer +public final class PluginModContainer extends ModContainer { private static final Logger LOGGER = LogManager.getLogger(); - public PluginModContainer(final IModInfo info, final String className, final ModFileScanData modFileScanData, final ModuleLayer moduleLayer) { - super(info, className, modFileScanData, moduleLayer); + private final ModFileScanData scanResults; + private final IEventBus eventBus; + private Object modInstance; + private final Class modClass; + public PluginModContainer(IModInfo info, String className, ModFileScanData modFileScanResults, ModuleLayer gameLayer) { + super(info); + LOGGER.debug(Logging.LOADING, "Creating PluginModContainer instance for {}", className); + this.scanResults = modFileScanResults; this.activityMap.put(ModLoadingStage.CONSTRUCT, this::constructPlugin); + this.eventBus = BusBuilder.builder().setExceptionHandler(this::onEventFailed).setTrackPhases(false).markerType(IModBusEvent.class).useModLauncher().build(); + this.configHandler = Optional.of(ce -> this.eventBus.post(ce.self())); + this.contextExtension = () -> null; + + try { + Module module = gameLayer.findModule(info.getOwningFile().moduleName()).orElseThrow(); + modClass = Class.forName(module, className); + LOGGER.trace(Logging.LOADING, "Loaded modclass {} with {}", modClass.getName(), modClass.getClassLoader()); + } catch (Throwable e) { + LOGGER.error(Logging.LOADING, "Failed to load class {}", className, e); + throw new ModLoadingException(info, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmodclass", e); + } + } + + private void onEventFailed(IEventBus iEventBus, Event event, IEventListener[] iEventListeners, int i, Throwable throwable) { + LOGGER.error(new EventBusErrorMessage(event, i, iEventListeners, throwable)); } private void constructPlugin() { - // TODO SF 1.19.4, replace accessor with reflection - final FMLModContainerAccessor accessor = (FMLModContainerAccessor) (Object) this; try { - PluginModContainer.LOGGER.trace(Logging.LOADING, "Loading plugin instance {} of type {}", getModId(), accessor.accessor$modClass().getName()); - final Injector childInjector = Launch.instance().lifecycle().platformInjector().createChildInjector(new PluginModule((PluginContainer) (Object) this, accessor.accessor$modClass())); - final Object instance = childInjector.getInstance(accessor.accessor$modClass()); - accessor.accessor$setModInstance(instance); - ((ForgeEventManager) MinecraftForge.EVENT_BUS).registerListeners((PluginContainer) (Object) this, instance); - PluginModContainer.LOGGER.trace(Logging.LOADING, "Loaded plugin instance {} of type {}", getModId(), accessor.accessor$modClass().getName()); - } catch (final Throwable e) { - PluginModContainer.LOGGER.error(Logging.LOADING,"Failed to create plugin instance. PluginID: {}, class {}", getModId(), accessor.accessor$modClass().getName(), e); - throw new ModLoadingException(this.modInfo, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmod", e, accessor.accessor$modClass()); + LOGGER.trace(Logging.LOADING, "Loading plugin instance {} of type {}", getModId(), this.modClass.getName()); + + final PluginContainer pluginContainer = ForgePluginContainer.of(this); + final Injector childInjector = Launch.instance().lifecycle().platformInjector().createChildInjector(new PluginModule(pluginContainer, this.modClass)); + this.modInstance = childInjector.getInstance(this.modClass); + ((ForgeEventManager) MinecraftForge.EVENT_BUS).registerListeners(pluginContainer, this.modInstance); + + LOGGER.trace(Logging.LOADING, "Loaded plugin instance {} of type {}", getModId(), this.modClass.getName()); + } catch (Throwable e) { + LOGGER.error(Logging.LOADING, "Failed to create plugin instance. PluginID: {}, class {}", getModId(), this.modClass.getName(), e); + throw new ModLoadingException(this.modInfo, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmod", e, this.modClass); } + + try { + LOGGER.trace(Logging.LOADING, "Injecting Automatic event subscribers for {}", getModId()); + AutomaticEventSubscriber.inject(this, this.scanResults, this.modClass.getClassLoader()); + LOGGER.trace(Logging.LOADING, "Completed Automatic event subscribers for {}", getModId()); + } catch (Throwable e) { + LOGGER.error(Logging.LOADING, "Failed to register automatic subscribers. PluginID: {}, class {}", getModId(), this.modClass.getName(), e); + throw new ModLoadingException(this.modInfo, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmod", e, this.modClass); + } + } + + @Override + public boolean matches(Object mod) { + return mod == this.modInstance; + } + + @Override + public Object getMod() { + return this.modInstance; + } + + @Override + protected void acceptEvent(final T e) { try { - PluginModContainer.LOGGER.trace(Logging.LOADING, "Injecting Automatic event subscribers for {}", getModId()); - AutomaticEventSubscriber.inject(this, accessor.accessor$scanResults(), accessor.accessor$modClass().getClassLoader()); - PluginModContainer.LOGGER.trace(Logging.LOADING, "Completed Automatic event subscribers for {}", getModId()); - } catch (final Throwable e) { - LOGGER.error(LOADING,"Failed to register automatic subscribers. PluginID: {}, class {}", getModId(), - accessor.accessor$modClass().getName(), e); - throw new ModLoadingException(this.modInfo, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmod", e, accessor.accessor$modClass()); + LOGGER.trace(Logging.LOADING, "Firing event for modid {} : {}", this.getModId(), e); + this.eventBus.post(e); + LOGGER.trace(Logging.LOADING, "Fired event for modid {} : {}", this.getModId(), e); + } catch (Throwable t) { + LOGGER.error(Logging.LOADING, "Caught exception during event {} dispatch for modid {}", e, this.getModId(), t); + throw new ModLoadingException(this.modInfo, this.modLoadingStage, "fml.modloading.errorduringevent", t); } } } diff --git a/forge/src/main/java/org/spongepowered/forge/bridge/minecraftforge/fml/ModContainerBridge.java b/forge/src/main/java/org/spongepowered/forge/bridge/minecraftforge/fml/ModContainerBridge.java deleted file mode 100644 index ac4c3972a26..00000000000 --- a/forge/src/main/java/org/spongepowered/forge/bridge/minecraftforge/fml/ModContainerBridge.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.bridge.minecraftforge.fml; - -import org.spongepowered.plugin.metadata.PluginMetadata; - -public interface ModContainerBridge { - - void bridge$setPluginMetadata(PluginMetadata metadata); -} diff --git a/forge/src/main/java/org/spongepowered/forge/bridge/minecraftforge/fml/ForgeRegistryBridge.java b/forge/src/main/java/org/spongepowered/forge/bridge/minecraftforge/registries/ForgeRegistryBridge.java similarity index 95% rename from forge/src/main/java/org/spongepowered/forge/bridge/minecraftforge/fml/ForgeRegistryBridge.java rename to forge/src/main/java/org/spongepowered/forge/bridge/minecraftforge/registries/ForgeRegistryBridge.java index 1ea6441e49c..66eda668cda 100644 --- a/forge/src/main/java/org/spongepowered/forge/bridge/minecraftforge/fml/ForgeRegistryBridge.java +++ b/forge/src/main/java/org/spongepowered/forge/bridge/minecraftforge/registries/ForgeRegistryBridge.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.forge.bridge.minecraftforge.fml; +package org.spongepowered.forge.bridge.minecraftforge.registries; import org.spongepowered.common.bridge.core.RegistryBridge; diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/fml/FMLModContainerMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/fml/FMLModContainerMixin_Forge.java deleted file mode 100644 index 0f9467f0021..00000000000 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/fml/FMLModContainerMixin_Forge.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.mixin.core.minecraftforge.fml; - -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.fml.javafmlmod.FMLModContainer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.forge.launch.event.ForgeEventManager; - -// TODO SF 1.19.4, we can no longer mixin into fml -@Mixin(value = FMLModContainer.class, remap = false) -public abstract class FMLModContainerMixin_Forge extends ModContainerMixin_Forge { - - private static final String forge$pluginModContainerName = "PluginModContainer"; - - // @formatter:off - @Shadow private Object modInstance; - // @formatter:on - - // TODO Need to figure out a way to make constructMod public, this is a nasty hack - @Inject(method = "constructMod", at = @At("HEAD"), cancellable = true) - private void forge$skipConstructModIfNotThisClass(final CallbackInfo ci) { - if (this.getClass().getSimpleName().equals(FMLModContainerMixin_Forge.forge$pluginModContainerName)) { - ci.cancel(); - } - } - - @Inject(method = "constructMod", at = @At("TAIL")) - private void forge$registerModForSpongeListeners(final CallbackInfo ci) { - if (this.modInstance != null) { - ((ForgeEventManager) MinecraftForge.EVENT_BUS).registerListeners(this, this.modInstance); - } - } - - @Override - public Object instance() { - return this.modInstance; - } -} diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/fml/ModContainerMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/fml/ModContainerMixin_Forge.java deleted file mode 100644 index 5e839e47e94..00000000000 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/fml/ModContainerMixin_Forge.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.mixin.core.minecraftforge.fml; - -import net.minecraftforge.fml.ModContainer; -import net.minecraftforge.fml.loading.moddiscovery.ModInfo; -import net.minecraftforge.forgespi.language.IModInfo; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.common.launch.Launch; -import org.spongepowered.forge.bridge.minecraftforge.fml.ModContainerBridge; -import org.spongepowered.forge.launch.ForgeLaunch; -import org.spongepowered.plugin.PluginContainer; -import org.spongepowered.plugin.metadata.PluginMetadata; - -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.Objects; -import java.util.Optional; -import java.util.function.Supplier; - -// TODO SF 1.19.4, we can no longer mixin into fml -@Mixin(value = ModContainer.class, remap = false) -public abstract class ModContainerMixin_Forge implements ModContainerBridge, PluginContainer { - - // @formatter:off - @Shadow @Final protected IModInfo modInfo; - @Shadow @Final protected String modId; - @Shadow protected Supplier contextExtension; - @Shadow public abstract Object shadow$getMod(); - // @formatter:on - - private Logger forge$logger; - private PluginMetadata forge$pluginMetadata; - - @Override - public PluginMetadata metadata() { - if (this.forge$pluginMetadata == null) { - this.forge$pluginMetadata = ((ForgeLaunch) Launch.instance()).metadataForMod((ModInfo) this.modInfo); - } - return this.forge$pluginMetadata; - } - - @Override - public void bridge$setPluginMetadata(final PluginMetadata metadata) { - this.forge$pluginMetadata = metadata; - } - - @Override - public Logger logger() { - if (this.forge$logger == null) { - this.forge$logger = LogManager.getLogger(this.modId); - } - return this.forge$logger; - } - - @Override - public Optional locateResource(URI relative) { - Objects.requireNonNull(relative, "relative"); - - final ClassLoader classLoader = this.shadow$getMod().getClass().getClassLoader(); - final URL resolved = classLoader.getResource(relative.getPath()); - try { - if (resolved == null) { - return Optional.empty(); - } - return Optional.of(resolved.toURI()); - } catch (final URISyntaxException ignored) { - return Optional.empty(); - } - } - - @Override - public Object instance() { - return this.contextExtension.get(); - } -} diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/core/ForgeRegistryMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/ForgeRegistryMixin_Forge.java similarity index 96% rename from forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/core/ForgeRegistryMixin_Forge.java rename to forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/ForgeRegistryMixin_Forge.java index a443d8a6c51..0ef16dbc122 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/core/ForgeRegistryMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/ForgeRegistryMixin_Forge.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.forge.mixin.core.minecraftforge.core; +package org.spongepowered.forge.mixin.core.minecraftforge.registries; import com.google.common.collect.Maps; import net.minecraft.core.Registry; @@ -40,7 +40,7 @@ import org.spongepowered.common.bridge.core.RegistryBridge; import org.spongepowered.common.registry.SpongeRegistryEntry; import org.spongepowered.common.registry.SpongeRegistryType; -import org.spongepowered.forge.bridge.minecraftforge.fml.ForgeRegistryBridge; +import org.spongepowered.forge.bridge.minecraftforge.registries.ForgeRegistryBridge; import java.util.Map; import java.util.StringJoiner; diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.json b/forge/src/mixins/resources/mixins.spongeforge.core.json index 336830e66ed..a4612e915e4 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.json @@ -15,7 +15,7 @@ "api.event.message.PlayerChatEventMixin_Forge", "commands.CommandsMixin_Forge", "minecraftforge.MinecraftForgeMixin_Forge", - "minecraftforge.core.ForgeRegistryMixin_Forge", + "minecraftforge.registries.ForgeRegistryMixin_Forge", "minecraftforge.event.ServerChatEventMixin_Forge", "minecraftforge.event.entity.EntityTravelToDimensionEventMixin_Forge", "minecraftforge.event.entity.player.PlayerEvent_PlayerChangedDimensionEventMixin_Forge",