Properly shutdown FMLModContainer's event bus when an error in a lifecycle event is detected.

This commit is contained in:
LexManos 2020-07-28 12:01:15 -07:00
parent 5104824a1b
commit 30bad1e26d
2 changed files with 46 additions and 12 deletions

View file

@ -23,22 +23,16 @@ import net.minecraft.entity.ai.attributes.Attribute;
import net.minecraft.entity.ai.attributes.RangedAttribute;
import net.minecraft.util.SoundEvent;
import net.minecraft.world.storage.IServerConfiguration;
import net.minecraft.world.storage.IWorldInfo;
import net.minecraft.world.storage.SaveFormat;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.*;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLModIdMappingEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.server.command.ConfigCommand;
import net.minecraftforge.server.command.ForgeCommand;
import net.minecraftforge.versions.forge.ForgeVersion;
import net.minecraftforge.versions.mcp.MCPVersion;
@ -112,7 +106,7 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
final IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.addListener(this::preInit);
modEventBus.addListener(this::gatherData);
modEventBus.register(this);
modEventBus.addGenericListener(IRecipeSerializer.class, this::registerRecipeSerialziers);
ATTRIBUTES.register(modEventBus);
MinecraftForge.EVENT_BUS.addListener(this::serverStopping);
MinecraftForge.EVENT_BUS.addGenericListener(SoundEvent.class, this::missingSoundMapping);
@ -125,7 +119,6 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
MinecraftForge.EVENT_BUS.addListener(VillagerTradingManager::loadTrades);
MinecraftForge.EVENT_BUS.register(MinecraftForge.INTERNAL_HANDLER);
MinecraftForge.EVENT_BUS.register(this);
}
public void preInit(FMLCommonSetupEvent evt)
@ -215,7 +208,6 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
}
}
@SubscribeEvent //ModBus, can't use addListener due to nested genetics.
public void registerRecipeSerialziers(RegistryEvent.Register<IRecipeSerializer<?>> event)
{
CraftingHelper.register(AndCondition.Serializer.INSTANCE);

View file

@ -30,13 +30,15 @@ import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModLoadingException;
import net.minecraftforge.fml.ModLoadingStage;
import net.minecraftforge.fml.event.lifecycle.IModBusEvent;
import net.minecraftforge.fml.event.lifecycle.ModLifecycleEvent;
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 java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
@ -90,7 +92,7 @@ public class FMLModContainer extends ModContainer
}
private Consumer<LifecycleEventProvider.LifecycleEvent> dummy() { return (s) -> {}; }
private Consumer<LifecycleEventProvider.LifecycleEvent> dummy() { return new ErroringConsumer<>(); }
private void onEventFailed(IEventBus iEventBus, Event event, IEventListener[] iEventListeners, int i, Throwable throwable)
{
@ -118,6 +120,7 @@ public class FMLModContainer extends ModContainer
private void afterEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent) {
if (getCurrentState() == ModLoadingStage.ERROR) {
LOGGER.error(LOADING,"An error occurred while dispatching event {} to {}", lifecycleEvent.fromStage(), getModId());
this.eventBus.shutdown();
}
}
@ -166,7 +169,46 @@ public class FMLModContainer extends ModContainer
}
@Override
protected void acceptEvent(final Event e) {
protected void acceptEvent(final Event e)
{
this.eventBus.post(e);
}
private class ErroringConsumer<T> implements Consumer<T>
{
private List<Consumer<? super T>> children = new ArrayList<>();
@Override
public void accept(T t)
{
Throwable error = null;
for (Consumer<? super T> child : children)
{
try
{
child.accept(t);
}
catch (Throwable e)
{
FMLModContainer.this.modLoadingStage = ModLoadingStage.ERROR;
error = e;
}
}
if (error != null)
{
if (error instanceof RuntimeException)
throw (RuntimeException)error;
throw new RuntimeException(error);
}
}
@Override
public ErroringConsumer<T> andThen(Consumer<? super T> after)
{
Objects.requireNonNull(after);
children.add(after);
return this;
}
}
}