diff --git a/src/main/java/net/minecraftforge/fml/ModContainer.java b/src/main/java/net/minecraftforge/fml/ModContainer.java index ad685edd3..efe3641aa 100644 --- a/src/main/java/net/minecraftforge/fml/ModContainer.java +++ b/src/main/java/net/minecraftforge/fml/ModContainer.java @@ -19,6 +19,7 @@ package net.minecraftforge.fml; +import cpw.mods.modlauncher.api.LamdbaExceptionUtils; import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.event.lifecycle.IModBusEvent; @@ -102,14 +103,13 @@ public abstract class ModContainer public static CompletableFuture buildTransitionHandler( final ModContainer target, final ModLoadingStage.EventGenerator eventGenerator, - final ModLoadingStage.EventDispatcher eventDispatcher, final BiFunction stateChangeHandler, final Executor executor) { return CompletableFuture .runAsync(() -> { ModLoadingContext.get().setActiveContainer(target, target.contextExtension.get()); target.activityMap.getOrDefault(target.modLoadingStage, ()->{}).run(); - eventDispatcher.apply(target::acceptEvent).accept(eventGenerator.apply(target)); + target.acceptEvent(eventGenerator.apply(target)); }, executor) .whenComplete((mc, exception) -> { target.modLoadingStage = stateChangeHandler.apply(target.modLoadingStage, exception); diff --git a/src/main/java/net/minecraftforge/fml/ModList.java b/src/main/java/net/minecraftforge/fml/ModList.java index e4d8e7da0..58a5bd15b 100644 --- a/src/main/java/net/minecraftforge/fml/ModList.java +++ b/src/main/java/net/minecraftforge/fml/ModList.java @@ -120,11 +120,10 @@ public class ModList Function>> futureVisitor( final ModLoadingStage.EventGenerator eventGenerator, - final ModLoadingStage.EventDispatcher eventManager, final BiFunction stateChange) { return executor -> gather( this.mods.stream() - .map(m -> ModContainer.buildTransitionHandler(m, eventGenerator, eventManager, stateChange, executor)) + .map(mod -> ModContainer.buildTransitionHandler(mod, eventGenerator, stateChange, executor)) .collect(Collectors.toList())) .thenComposeAsync(ModList::completableFutureFromExceptionList, executor); } diff --git a/src/main/java/net/minecraftforge/fml/ModLoadingStage.java b/src/main/java/net/minecraftforge/fml/ModLoadingStage.java index d7782fa4c..57c37a2c5 100644 --- a/src/main/java/net/minecraftforge/fml/ModLoadingStage.java +++ b/src/main/java/net/minecraftforge/fml/ModLoadingStage.java @@ -34,6 +34,7 @@ import net.minecraftforge.fml.event.lifecycle.ParallelDispatchEvent; import net.minecraftforge.registries.GameData; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -50,8 +51,8 @@ public enum ModLoadingStage ERROR(), VALIDATE(), CONSTRUCT(FMLConstructModEvent.class), - CREATE_REGISTRIES(()->Stream.of(EventGenerator.fromFunction(RegistryEvent.NewRegistry::new)), EventDispatcher.identity()), - LOAD_REGISTRIES(GameData::generateRegistryEvents, GameData.buildRegistryEventDispatch()), + CREATE_REGISTRIES(()->Stream.of(EventGenerator.fromFunction(RegistryEvent.NewRegistry::new))), + LOAD_REGISTRIES(GameData::generateRegistryEvents, GameData::preRegistryEventDispatch, GameData::postRegistryEventDispatch), COMMON_SETUP(FMLCommonSetupEvent.class), SIDED_SETUP(DistExecutor.unsafeRunForDist(()->()->FMLClientSetupEvent.class, ()->()->FMLDedicatedServerSetupEvent.class)), ENQUEUE_IMC(InterModEnqueueEvent.class), @@ -60,30 +61,37 @@ public enum ModLoadingStage DONE(); private final Supplier>> eventFunctionStream; - private final EventDispatcher eventManager; private final Optional> parallelEventClass; private final ThreadSelector threadSelector; private final BiFunction>, CompletableFuture>> finalActivityGenerator; + private final BiFunction, CompletableFuture>> preDispatchHook; + private final BiFunction, CompletableFuture>> postDispatchHook; private DeferredWorkQueue deferredWorkQueue; ModLoadingStage(Class parallelClass) { final EventGenerator event = EventGenerator.fromFunction(LamdbaExceptionUtils.rethrowFunction((ModContainer mc) -> parallelClass.getConstructor(ModContainer.class).newInstance(mc))); this.eventFunctionStream = ()->Stream.of(event); this.threadSelector = ThreadSelector.PARALLEL; - this.eventManager = EventDispatcher.identity(); this.parallelEventClass = Optional.of(parallelClass); deferredWorkQueue = new DeferredWorkQueue(this, parallelClass); this.finalActivityGenerator = (e, prev) -> prev.thenApplyAsync((List t) -> { deferredWorkQueue.runTasks(); return t; }, e); + this.preDispatchHook = (t,f)->CompletableFuture.completedFuture(Collections.emptyList()); + this.postDispatchHook = (t,f)->CompletableFuture.completedFuture(Collections.emptyList()); } - ModLoadingStage(Supplier>> eventStream, EventDispatcher eventManager) { + ModLoadingStage(Supplier>> eventStream) { + this(eventStream, (t,f)->CompletableFuture.completedFuture(Collections.emptyList()), (t,f)->CompletableFuture.completedFuture(Collections.emptyList())); + } + @SuppressWarnings("unchecked") + ModLoadingStage(Supplier>> eventStream, final BiFunction, CompletableFuture>> preDispatchHook, final BiFunction, CompletableFuture>> postDispatchHook) { this.eventFunctionStream = eventStream; this.parallelEventClass = Optional.empty(); - this.eventManager = eventManager; this.threadSelector = ThreadSelector.SYNC; + this.preDispatchHook = preDispatchHook; + this.postDispatchHook = postDispatchHook; this.finalActivityGenerator = (e, prev) ->prev.thenApplyAsync(Function.identity(), e); } @@ -97,17 +105,10 @@ public enum ModLoadingStage @SuppressWarnings("unchecked") public CompletableFuture> buildTransition(final Executor syncExecutor, final Executor parallelExecutor, Function> preSyncTask, Function> postSyncTask) { List>> cfs = new ArrayList<>(); - EventDispatcher em = (EventDispatcher) this.eventManager; - eventFunctionStream.get() + this.eventFunctionStream.get() .map(f->(EventGenerator)f) - .reduce((head, tail)->{ - cfs.add(ModList.get() - .futureVisitor(head, em, ModLoadingStage::currentState) - .apply(threadSelector.apply(syncExecutor, parallelExecutor)) - ); - return tail; - }) - .ifPresent(last->cfs.add(ModList.get().futureVisitor(last, em, ModLoadingStage::nextState).apply(threadSelector.apply(syncExecutor, parallelExecutor)))); + .reduce((head, tail)-> addCompletableFutureTaskForModDispatch(syncExecutor, parallelExecutor, cfs, head, ModLoadingStage::currentState, tail)) + .ifPresent(last-> addCompletableFutureTaskForModDispatch(syncExecutor, parallelExecutor, cfs, last, ModLoadingStage::nextState, null)); final CompletableFuture preSyncTaskCF = preSyncTask.apply(syncExecutor); final CompletableFuture> eventDispatchCF = ModList.gather(cfs).thenCompose(ModList::completableFutureFromExceptionList); final CompletableFuture> postEventDispatchCF = preSyncTaskCF.thenComposeAsync(n -> eventDispatchCF, parallelExecutor).thenApply(r -> { @@ -117,6 +118,14 @@ public enum ModLoadingStage return this.finalActivityGenerator.apply(syncExecutor, postEventDispatchCF); } + @SuppressWarnings("unchecked") + private EventGenerator addCompletableFutureTaskForModDispatch(final Executor syncExecutor, final Executor parallelExecutor, final List>> completeableFutures, final EventGenerator eventGenerator, BiFunction nextState, final EventGenerator nextGenerator) { + completeableFutures.add(((BiFunction, CompletableFuture>>)preDispatchHook).apply(threadSelector.apply(syncExecutor, parallelExecutor), eventGenerator)); + completeableFutures.add(ModList.get().futureVisitor(eventGenerator, nextState).apply(threadSelector.apply(syncExecutor, parallelExecutor))); + completeableFutures.add(((BiFunction, CompletableFuture>>)postDispatchHook).apply(threadSelector.apply(syncExecutor, parallelExecutor), eventGenerator)); + return nextGenerator; + } + ModLoadingStage nextState(Throwable exception) { return exception != null ? ERROR : values()[this.ordinal()+1]; } @@ -153,9 +162,4 @@ public enum ModLoadingStage return fn::apply; } } - public interface EventDispatcher extends Function, Consumer> { - static EventDispatcher identity() { - return consumer -> consumer; - } - } } diff --git a/src/main/java/net/minecraftforge/registries/GameData.java b/src/main/java/net/minecraftforge/registries/GameData.java index 836d8d9e3..ffebdfbe6 100644 --- a/src/main/java/net/minecraftforge/registries/GameData.java +++ b/src/main/java/net/minecraftforge/registries/GameData.java @@ -22,8 +22,8 @@ package net.minecraftforge.registries; import com.google.common.collect.*; import com.mojang.serialization.Lifecycle; -import java.util.HashSet; -import java.util.Set; +import java.util.*; + import net.minecraft.block.AirBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -92,12 +92,8 @@ import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; import java.lang.reflect.Field; -import java.util.Collection; -import java.util.IdentityHashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Function; @@ -346,22 +342,30 @@ public class GameData keys.add(0, BLOCKS.func_240901_a_()); keys.add(1, ITEMS.func_240901_a_()); - final Function> modContainerEventGeneratorFunction = rl -> RegistryManager.ACTIVE.getRegistry(rl).getRegisterEvent(rl); - return keys.stream().map(rl -> ModLoadingStage.EventGenerator.fromFunction(mc -> modContainerEventGeneratorFunction.apply(rl))); + final Function> registerEventGenerator = rl -> RegistryManager.ACTIVE.getRegistry(rl).getRegisterEvent(rl); + return keys.stream().map(rl -> ModLoadingStage.EventGenerator.fromFunction(mc -> registerEventGenerator.apply(rl))); } - public static ModLoadingStage.EventDispatcher> buildRegistryEventDispatch() { - return eventConsumer -> eventToSend -> { - final ResourceLocation rl = eventToSend.getName(); - ForgeRegistry fr = (ForgeRegistry) eventToSend.getRegistry(); - StartupMessageManager.modLoaderConsumer().ifPresent(s->s.accept("REGISTERING "+rl)); - fr.unfreeze(); - eventConsumer.accept(eventToSend); + public static CompletableFuture> preRegistryEventDispatch(final Executor executor, final ModLoadingStage.EventGenerator> eventGenerator) { + return CompletableFuture.runAsync(()-> { + final RegistryEvent.Register event = eventGenerator.apply(null); + final ResourceLocation rl = event.getName(); + ForgeRegistry fr = (ForgeRegistry) event.getRegistry(); + StartupMessageManager.modLoaderConsumer().ifPresent(s -> s.accept("REGISTERING " + rl)); + fr.unfreeze(); + }, executor).thenApply(v->Collections.emptyList()); + } + + public static CompletableFuture> postRegistryEventDispatch(final Executor executor, final ModLoadingStage.EventGenerator> eventGenerator) { + return CompletableFuture.runAsync(()-> { + final RegistryEvent.Register event = eventGenerator.apply(null); + final ResourceLocation rl = event.getName(); + ForgeRegistry fr = (ForgeRegistry) event.getRegistry(); fr.freeze(); - LOGGER.debug(REGISTRIES,"Applying holder lookups: {}", rl.toString()); + LOGGER.debug(REGISTRIES, "Applying holder lookups: {}", rl.toString()); ObjectHolderRegistry.applyObjectHolders(rl::equals); - LOGGER.debug(REGISTRIES,"Holder lookups applied: {}", rl.toString()); - }; + LOGGER.debug(REGISTRIES, "Holder lookups applied: {}", rl.toString()); + }, executor).thenApply(v->Collections.emptyList()); } public static void setCustomTagTypesFromRegistries()