Some more stuffs. ObjectHolder's replacement?

This commit is contained in:
cpw 2018-06-19 14:04:05 -04:00 committed by LexManos
parent baa9dfe55a
commit 06b16aaa19
47 changed files with 987 additions and 269 deletions

View file

@ -20,11 +20,10 @@
package net.minecraftforge.client.event; package net.minecraftforge.client.event;
import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.common.eventhandler.IContextSetter;
/** /**
* Fired when the {@link net.minecraftforge.client.model.ModelLoader} is ready to receive registrations * Fired when the {@link net.minecraftforge.client.model.ModelLoader} is ready to receive registrations
*/ */
public class ModelRegistryEvent extends Event implements IContextSetter public class ModelRegistryEvent extends Event
{ {
} }

View file

@ -22,50 +22,30 @@ package net.minecraftforge.common.capabilities;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap; import java.util.IdentityHashMap;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import net.minecraftforge.fml.language.ModFileScanData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import java.util.function.Function; import java.util.function.Function;
import com.google.common.base.Preconditions; import java.util.stream.Collectors;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.minecraftforge.common.util.EnumHelper; import net.minecraftforge.common.util.EnumHelper;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.discovery.ASMDataTable; import static net.minecraftforge.fml.Logging.CAPABILITIES;
public enum CapabilityManager public enum CapabilityManager
{ {
INSTANCE; INSTANCE;
private static final Logger LOGGER = LogManager.getLogger("FML");
/**
* Registers a capability to be consumed by others.
* APIs who define the capability should call this.
* To retrieve the Capability instance, use the @CapabilityInject annotation.
*
* @param type The Interface to be registered
* @param storage A default implementation of the storage handler.
* @param implementation A default implementation of the interface.
* @deprecated Use the overload that takes a factory instead of a class.
* You can easily do this by passing a constructor reference
* (MyImpl::new instead of MyImpl.class). TODO remove in 1.13.
*/
@Deprecated
public <T> void register(Class<T> type, Capability.IStorage<T> storage, final Class<? extends T> implementation)
{
Preconditions.checkArgument(implementation != null, "Attempted to register a capability with no default implementation");
register(type, storage, () ->
{
try {
return implementation.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
});
}
/** /**
* Registers a capability to be consumed by others. * Registers a capability to be consumed by others.
@ -78,103 +58,95 @@ public enum CapabilityManager
*/ */
public <T> void register(Class<T> type, Capability.IStorage<T> storage, Callable<? extends T> factory) public <T> void register(Class<T> type, Capability.IStorage<T> storage, Callable<? extends T> factory)
{ {
Preconditions.checkArgument(type != null, "Attempted to register a capability with invalid type"); Objects.requireNonNull(type,"Attempted to register a capability with invalid type");
Preconditions.checkArgument(storage != null, "Attempted to register a capability with no storage implementation"); Objects.requireNonNull(storage,"Attempted to register a capability with no storage implementation");
Preconditions.checkArgument(factory != null, "Attempted to register a capability with no default implementation factory"); Objects.requireNonNull(factory,"Attempted to register a capability with no default implementation factory");
String realName = type.getName().intern(); String realName = type.getName().intern();
Preconditions.checkState(!providers.containsKey(realName), "Can not register a capability implementation multiple times: %s", realName); if (providers.containsKey(realName)) {
LOGGER.error(CAPABILITIES, "Cannot register capability implementation multiple times : {}", realName);
throw new IllegalArgumentException("Cannot register a capability implementation multiple times : "+ realName);
}
Capability<T> cap = new Capability<T>(realName, storage, factory); Capability<T> cap = new Capability<>(realName, storage, factory);
providers.put(realName, cap); providers.put(realName, cap);
List<Function<Capability<?>, Object>> list = callbacks.get(realName); callbacks.getOrDefault(realName, Collections.emptyList()).forEach(func -> func.apply(cap));
if (list != null)
{
for (Function<Capability<?>, Object> func : list)
{
func.apply(cap);
}
}
} }
// INTERNAL // INTERNAL
private IdentityHashMap<String, Capability<?>> providers = Maps.newIdentityHashMap(); private IdentityHashMap<String, Capability<?>> providers = new IdentityHashMap<>();
private IdentityHashMap<String, List<Function<Capability<?>, Object>>> callbacks = Maps.newIdentityHashMap(); private IdentityHashMap<String, List<Function<Capability<?>, Object>>> callbacks = new IdentityHashMap<>();
public void injectCapabilities(ASMDataTable data) public void injectCapabilities(List<ModFileScanData> data)
{ {
for (ASMDataTable.ASMData entry : data.getAll(CapabilityInject.class.getName())) final List<ModFileScanData.AnnotationData> capabilities = data.stream().map(ModFileScanData::getAnnotations).flatMap(Collection::stream).
filter(a -> Objects.equals(a.getClassType(), Type.getType(CapabilityInject.class))).
collect(Collectors.toList());
capabilities.forEach(this::attachCapabilityToMethod);
}
private void attachCapabilityToMethod(ModFileScanData.AnnotationData entry)
{
final String targetClass = entry.getClassType().getClassName();
final String targetName = entry.getMemberName();
Type type = (Type)entry.getAnnotationData().get("value");
if (type == null)
{ {
final String targetClass = entry.getClassName(); LOGGER.warn(CAPABILITIES,"Unable to inject capability at {}.{} (Invalid Annotation)", targetClass, targetName);
final String targetName = entry.getObjectName(); return;
Type type = (Type)entry.getAnnotationInfo().get("value"); }
if (type == null) final String capabilityName = type.getInternalName().replace('/', '.').intern();
{
FMLLog.log.warn("Unable to inject capability at {}.{} (Invalid Annotation)", targetClass, targetName);
continue;
}
final String capabilityName = type.getInternalName().replace('/', '.').intern();
List<Function<Capability<?>, Object>> list = callbacks.computeIfAbsent(capabilityName, k -> Lists.newArrayList()); List<Function<Capability<?>, Object>> list = callbacks.computeIfAbsent(capabilityName, k -> new ArrayList<>());
if (entry.getObjectName().indexOf('(') > 0) if (entry.getMemberName().indexOf('(') > 0)
{ {
list.add(new Function<Capability<?>, Object>() list.add(input -> {
try
{ {
@Override for (Method mtd : Class.forName(targetClass).getDeclaredMethods())
public Object apply(Capability<?> input)
{ {
try if (targetName.equals(mtd.getName() + Type.getMethodDescriptor(mtd)))
{ {
for (Method mtd : Class.forName(targetClass).getDeclaredMethods()) if ((mtd.getModifiers() & Modifier.STATIC) != Modifier.STATIC)
{ {
if (targetName.equals(mtd.getName() + Type.getMethodDescriptor(mtd))) LOGGER.warn(CAPABILITIES,"Unable to inject capability {} at {}.{} (Non-Static)", capabilityName, targetClass, targetName);
{
if ((mtd.getModifiers() & Modifier.STATIC) != Modifier.STATIC)
{
FMLLog.log.warn("Unable to inject capability {} at {}.{} (Non-Static)", capabilityName, targetClass, targetName);
return null;
}
mtd.setAccessible(true);
mtd.invoke(null, input);
return null;
}
}
FMLLog.log.warn("Unable to inject capability {} at {}.{} (Method Not Found)", capabilityName, targetClass, targetName);
}
catch (Exception e)
{
FMLLog.log.warn("Unable to inject capability {} at {}.{}", capabilityName, targetClass, targetName, e);
}
return null;
}
});
}
else
{
list.add(new Function<Capability<?>, Object>()
{
@Override
public Object apply(Capability<?> input)
{
try
{
Field field = Class.forName(targetClass).getDeclaredField(targetName);
if ((field.getModifiers() & Modifier.STATIC) != Modifier.STATIC)
{
FMLLog.log.warn("Unable to inject capability {} at {}.{} (Non-Static)", capabilityName, targetClass, targetName);
return null; return null;
} }
EnumHelper.setFailsafeFieldValue(field, null, input);
} mtd.setAccessible(true);
catch (Exception e) mtd.invoke(null, input);
{ return null;
FMLLog.log.warn("Unable to inject capability {} at {}.{}", capabilityName, targetClass, targetName, e);
} }
}
LOGGER.warn(CAPABILITIES,"Unable to inject capability {} at {}.{} (Method Not Found)", capabilityName, targetClass, targetName);
}
catch (Exception e)
{
LOGGER.warn(CAPABILITIES,"Unable to inject capability {} at {}.{}", capabilityName, targetClass, targetName, e);
}
return null;
});
}
else
{
list.add(input -> {
try
{
Field field = Class.forName(targetClass).getDeclaredField(targetName);
if ((field.getModifiers() & Modifier.STATIC) != Modifier.STATIC)
{
LOGGER.warn(CAPABILITIES,"Unable to inject capability {} at {}.{} (Non-Static)", capabilityName, targetClass, targetName);
return null; return null;
} }
}); // TODO Remove enumhelper here
} EnumHelper.setFailsafeFieldValue(field, null, input);
}
catch (Exception e)
{
LOGGER.warn(CAPABILITIES,"Unable to inject capability {} at {}.{}", capabilityName, targetClass, targetName, e);
}
return null;
});
} }
} }
} }

View file

@ -30,6 +30,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import java.util.Arrays;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -52,7 +53,9 @@ public class AutomaticEventSubscriber
collect(Collectors.toList()); collect(Collectors.toList());
ebsTargets.forEach(ad -> { ebsTargets.forEach(ad -> {
final List<ModAnnotation.EnumHolder> sidesValue = (List<ModAnnotation.EnumHolder>)ad.getAnnotationData().get("value"); @SuppressWarnings("unchecked")
final List<ModAnnotation.EnumHolder> sidesValue = (List<ModAnnotation.EnumHolder>)ad.getAnnotationData().
getOrDefault("value", Arrays.asList(new ModAnnotation.EnumHolder(null, "CLIENT"), new ModAnnotation.EnumHolder(null, "SERVER")));
final EnumSet<Side> sides = sidesValue.stream().map(eh -> Side.valueOf(eh.getValue())). final EnumSet<Side> sides = sidesValue.stream().map(eh -> Side.valueOf(eh.getValue())).
collect(Collectors.toCollection(() -> EnumSet.noneOf(Side.class))); collect(Collectors.toCollection(() -> EnumSet.noneOf(Side.class)));
final String modId = (String)ad.getAnnotationData().getOrDefault("modId", mod.getModId()); final String modId = (String)ad.getAnnotationData().getOrDefault("modId", mod.getModId());

View file

@ -0,0 +1,44 @@
/*
* 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 java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
public class DeferredWorkQueue
{
public static ConcurrentLinkedDeque<FutureWorkTask<?>> deferredWorkQueue = new ConcurrentLinkedDeque<>();
public static <T> Future<T> enqueueWork(Callable<T> workToEnqueue) {
final FutureWorkTask<T> workTask = new FutureWorkTask<>(workToEnqueue);
DeferredWorkQueue.deferredWorkQueue.add(workTask);
return workTask;
}
public static class FutureWorkTask<T> extends FutureTask<T>
{
FutureWorkTask(Callable<T> callable)
{
super(callable);
}
}
}

View file

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.language; package net.minecraftforge.fml;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;

View file

@ -19,7 +19,6 @@
package net.minecraftforge.fml; package net.minecraftforge.fml;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.common.event.ModLifecycleEvent; import net.minecraftforge.fml.common.event.ModLifecycleEvent;
import net.minecraftforge.fml.javafmlmod.FMLModContainer; import net.minecraftforge.fml.javafmlmod.FMLModContainer;
@ -27,8 +26,12 @@ import java.util.function.Supplier;
public enum LifecycleEventProvider public enum LifecycleEventProvider
{ {
LOAD(()->new LifecycleEvent(ModLoadingStage.BEGIN)), CONSTRUCT(()->new LifecycleEvent(ModLoadingStage.CONSTRUCT)),
CONSTRUCT(()->new LifecycleEvent(ModLoadingStage.CONSTRUCT)); PREINIT(()->new LifecycleEvent(ModLoadingStage.PREINIT)),
SIDEDINIT(()->new LifecycleEvent(ModLoadingStage.SIDEDINIT)),
INIT(()->new LifecycleEvent(ModLoadingStage.INIT)),
POSTINIT(()->new LifecycleEvent(ModLoadingStage.POSTINIT)),
COMPLETE(()->new LifecycleEvent(ModLoadingStage.COMPLETE));
public void dispatch() { public void dispatch() {
ModList.get().dispatchLifeCycleEvent(this.event.get()); ModList.get().dispatchLifeCycleEvent(this.event.get());

View file

@ -35,5 +35,6 @@ public class Logging
public static final Marker LOADING = MarkerManager.getMarker("LOADING"); public static final Marker LOADING = MarkerManager.getMarker("LOADING");
public static final Marker SCAN = MarkerManager.getMarker("SCAN"); public static final Marker SCAN = MarkerManager.getMarker("SCAN");
public static final Marker SPLASH = MarkerManager.getMarker("SPLASH"); public static final Marker SPLASH = MarkerManager.getMarker("SPLASH");
public static final Marker CAPABILITIES = MarkerManager.getMarker("CAPABILITIES");
public static final Marker MODELLOADING = MarkerManager.getMarker("MODELLOADING"); public static final Marker MODELLOADING = MarkerManager.getMarker("MODELLOADING");
} }

View file

@ -19,7 +19,6 @@
package net.minecraftforge.fml; package net.minecraftforge.fml;
import net.minecraftforge.fml.language.ExtensionPoint;
import net.minecraftforge.fml.language.IModInfo; import net.minecraftforge.fml.language.IModInfo;
import java.util.ArrayList; import java.util.ArrayList;
@ -59,7 +58,7 @@ public abstract class ModContainer
this.modInfo = info; this.modInfo = info;
this.triggerMap = new HashMap<>(); this.triggerMap = new HashMap<>();
this.modLoadingError = new ArrayList<>(); this.modLoadingError = new ArrayList<>();
this.modLoadingStage = ModLoadingStage.BEGIN; this.modLoadingStage = ModLoadingStage.CONSTRUCT;
} }
/** /**
@ -101,6 +100,7 @@ public abstract class ModContainer
} }
catch (RuntimeException e) catch (RuntimeException e)
{ {
modLoadingError.add(e);
modLoadingStage = ModLoadingStage.ERROR; modLoadingStage = ModLoadingStage.ERROR;
} }
} }

View file

@ -20,31 +20,45 @@
package net.minecraftforge.fml; package net.minecraftforge.fml;
import com.google.common.collect.Streams; import com.google.common.collect.Streams;
import net.minecraftforge.fml.javafmlmod.ModLoadingContext;
import net.minecraftforge.fml.language.ModFileScanData;
import net.minecraftforge.fml.loading.DefaultModInfos; import net.minecraftforge.fml.loading.DefaultModInfos;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.loading.moddiscovery.BackgroundScanHandler; import net.minecraftforge.fml.loading.moddiscovery.BackgroundScanHandler;
import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo; import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo; 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.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.FutureTask;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static net.minecraftforge.fml.Logging.LOADING;
/** /**
* Master list of all mods * Master list of all mods - game-side version. This is classloaded in the game scope and
* can dispatch game level events as a result.
*/ */
public class ModList public class ModList
{ {
private static Logger LOGGER = LogManager.getLogger("FML");
private static ModList INSTANCE; private static ModList INSTANCE;
private final List<ModFileInfo> modFiles; private final List<ModFileInfo> modFiles;
private final List<ModInfo> sortedList; private final List<ModInfo> sortedList;
private final Map<String, ModFileInfo> fileById; private final Map<String, ModFileInfo> fileById;
private BackgroundScanHandler scanner;
private List<ModContainer> mods; private List<ModContainer> mods;
private Map<String, ModContainer> indexedMods; private Map<String, ModContainer> indexedMods;
private ForkJoinPool modLoadingThreadPool = new ForkJoinPool();
private List<ModFileScanData> modFileScanData;
private ModList(final List<ModFile> modFiles, final List<ModInfo> sortedList) private ModList(final List<ModFile> modFiles, final List<ModInfo> sortedList)
{ {
@ -79,10 +93,21 @@ public class ModList
} }
public void dispatchLifeCycleEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent) { public void dispatchLifeCycleEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent) {
this.mods.parallelStream().forEach(m->m.transitionState(lifecycleEvent)); FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.preLifecycleEvent(lifecycleEvent));
DeferredWorkQueue.deferredWorkQueue.clear();
try
{
modLoadingThreadPool.submit(()->this.mods.parallelStream().forEach(m->m.transitionState(lifecycleEvent))).get();
}
catch (InterruptedException | ExecutionException e)
{
LOGGER.error(LOADING, "Encountered an exception during parallel processing", e);
}
DeferredWorkQueue.deferredWorkQueue.forEach(FutureTask::run);
FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.postLifecycleEvent(lifecycleEvent));
final List<ModContainer> erroredContainers = this.mods.stream().filter(m -> m.getCurrentState() == ModLoadingStage.ERROR).collect(Collectors.toList()); final List<ModContainer> erroredContainers = this.mods.stream().filter(m -> m.getCurrentState() == ModLoadingStage.ERROR).collect(Collectors.toList());
if (!erroredContainers.isEmpty()) { if (!erroredContainers.isEmpty()) {
throw new RuntimeException("Errored containers found!"); throw new RuntimeException("Errored containers found!", erroredContainers.get(0).modLoadingError.get(0));
} }
} }
@ -92,9 +117,10 @@ public class ModList
this.indexedMods = modContainers.stream().collect(Collectors.toMap(ModContainer::getModId, Function.identity())); this.indexedMods = modContainers.stream().collect(Collectors.toMap(ModContainer::getModId, Function.identity()));
} }
public Optional<Object> getModObjectById(String modId) @SuppressWarnings("unchecked")
public <T> Optional<T> getModObjectById(String modId)
{ {
return getModContainerById(modId).map(ModContainer::getMod); return getModContainerById(modId).map(ModContainer::getMod).map(o -> (T) o);
} }
public Optional<? extends ModContainer> getModContainerById(String modId) public Optional<? extends ModContainer> getModContainerById(String modId)
@ -111,4 +137,24 @@ public class ModList
{ {
return this.indexedMods.containsKey(modTarget); return this.indexedMods.containsKey(modTarget);
} }
public int size()
{
return mods.size();
}
public List<ModFileScanData> getAllScanData()
{
if (modFileScanData == null)
{
modFileScanData = this.sortedList.stream().
map(ModInfo::getOwningFile).
filter(Objects::nonNull).
map(ModFileInfo::getFile).
map(ModFile::getScanResult).
collect(Collectors.toList());
}
return modFileScanData;
}
} }

View file

@ -19,17 +19,24 @@
package net.minecraftforge.fml; package net.minecraftforge.fml;
import net.minecraftforge.api.Side;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.fml.language.IModInfo; import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.loading.LoadingModList; import net.minecraftforge.fml.loading.LoadingModList;
import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo; import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.registries.GameData;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -55,15 +62,24 @@ public class ModLoader
return INSTANCE == null ? INSTANCE = new ModLoader() : INSTANCE; return INSTANCE == null ? INSTANCE = new ModLoader() : INSTANCE;
} }
private static Callable<Boolean> fireClientEvents()
{
return ()->MinecraftForge.EVENT_BUS.post(new ModelRegistryEvent());
}
public void loadMods() { public void loadMods() {
final ModList modList = ModList.of(loadingModList.getModFiles().stream().map(ModFileInfo::getFile).collect(Collectors.toList()), loadingModList.getMods()); final ModList modList = ModList.of(loadingModList.getModFiles().stream().map(ModFileInfo::getFile).collect(Collectors.toList()), loadingModList.getMods());
modList.setLoadedMods(loadingModList.getModFiles().stream(). modList.setLoadedMods(loadingModList.getModFiles().stream().
map(ModFileInfo::getFile). map(ModFileInfo::getFile).
map(mf -> buildMods(mf, modClassLoader)). map(mf -> buildMods(mf, modClassLoader)).
flatMap(Collection::stream).collect(Collectors.toList())); flatMap(Collection::stream).collect(Collectors.toList()));
LifecycleEventProvider.LOAD.dispatch();
LifecycleEventProvider.CONSTRUCT.dispatch(); LifecycleEventProvider.CONSTRUCT.dispatch();
GameData.fireCreateRegistryEvents();
CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData());
LifecycleEventProvider.PREINIT.dispatch();
GameData.fireRegistryEvents(rl -> !Objects.equals(rl, GameData.RECIPES));
SidedExecutor.runOn(Side.CLIENT, ModLoader::fireClientEvents);
LifecycleEventProvider.SIDEDINIT.dispatch();
} }
private List<ModContainer> buildMods(final ModFile modFile, final ModLoadingClassLoader modClassLoader) private List<ModContainer> buildMods(final ModFile modFile, final ModLoadingClassLoader modClassLoader)
@ -76,4 +92,10 @@ public class ModLoader
} }
public void finishMods()
{
LifecycleEventProvider.INIT.dispatch();
LifecycleEventProvider.POSTINIT.dispatch();
LifecycleEventProvider.COMPLETE.dispatch();
}
} }

View file

@ -0,0 +1,34 @@
/*
* 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 java.util.ArrayList;
import java.util.List;
/**
* Accumulates errors during loading for compact handling
*/
public class ModLoadingException extends RuntimeException
{
private List<ErrorEvent> errorEvents = new ArrayList<>();
public static class ErrorEvent {
}
}

View file

@ -31,12 +31,13 @@ import java.util.function.Supplier;
public enum ModLoadingStage public enum ModLoadingStage
{ {
ERROR(null), ERROR(null),
BEGIN(null), CONSTRUCT(null),
CONSTRUCT(()->FMLPreInitializationEvent::new), PREINIT(()->FMLPreInitializationEvent::new),
PREINIT(()->FMLInitializationEvent::new), SIDEDINIT(SidedProvider.SIDEDINIT::get),
INIT(()->FMLPostInitializationEvent::new), INIT(()->FMLInitializationEvent::new),
POSTINIT(()->FMLLoadCompleteEvent::new), POSTINIT(()->FMLPostInitializationEvent::new),
COMPLETE(null); COMPLETE(()->FMLLoadCompleteEvent::new),
DONE(null);
private final Supplier<Function<ModContainer, ModLifecycleEvent>> modLifecycleEventFunction; private final Supplier<Function<ModContainer, ModLifecycleEvent>> modLifecycleEventFunction;

View file

@ -0,0 +1,241 @@
/*
* 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 java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public final class OptionalMod<T>
{
private final String modId;
private T value;
private boolean searched;
public static <M> OptionalMod<M> of(final String modId) {
return new OptionalMod<>(modId);
}
private static OptionalMod<?> EMPTY = new OptionalMod<>(true);
private static <T> OptionalMod<T> empty() {
@SuppressWarnings("unchecked")
OptionalMod<T> t = (OptionalMod<T>) EMPTY;
return t;
}
private OptionalMod(boolean searched) {
this.searched = searched;
this.modId = "";
}
private OptionalMod(String modId)
{
this.modId = modId;
}
private T getValue()
{
if (!searched) {
this.value = ModList.get().<T>getModObjectById(this.modId).orElse(null);
searched = true;
}
return this.value;
}
/**
* If a mod is present in this {@code OptionalMod}, returns the value,
* otherwise throws {@code NoSuchElementException}.
*
* @return the modobject held by this {@code OptionalMod}
* @throws NoSuchElementException if there is no modobject present
*
* @see Optional#isPresent()
*/
public T get() {
if (getValue() == null) {
throw new NoSuchElementException("No value present");
}
return getValue();
}
public String getModId() {
return this.modId;
}
/**
* Return {@code true} if there is a mod object present, otherwise {@code false}.
*
* @return {@code true} if there is a mod object present, otherwise {@code false}
*/
public boolean isPresent() {
return getValue() != null;
}
/**
* If a mod object is present, invoke the specified consumer with the object,
* otherwise do nothing.
*
* @param consumer block to be executed if a mod object is present
* @throws NullPointerException if mod object is present and {@code consumer} is
* null
*/
public void ifPresent(Consumer<? super T> consumer) {
if (getValue() != null)
consumer.accept(getValue());
}
/**
* If a mod object is present, and the mod object matches the given predicate,
* return an {@code OptionalMod} describing the value, otherwise return an
* empty {@code OptionalMod}.
*
* @param predicate a predicate to apply to the mod object, if present
* @return an {@code OptionalMod} describing the value of this {@code OptionalMod}
* if a mod object is present and the mod object matches the given predicate,
* otherwise an empty {@code OptionalMod}
* @throws NullPointerException if the predicate is null
*/
public OptionalMod<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(getValue()) ? this : empty();
}
/**
* If a mod object is present, apply the provided mapping function to it,
* and if the result is non-null, return an {@code Optional} describing the
* result. Otherwise return an empty {@code Optional}.
*
* @apiNote This method supports post-processing on optional values, without
* the need to explicitly check for a return status.
*
* @param <U> The type of the result of the mapping function
* @param mapper a mapping function to apply to the mod object, if present
* @return an {@code Optional} describing the result of applying a mapping
* function to the mod object of this {@code OptionalMod}, if a mod object is present,
* otherwise an empty {@code Optional}
* @throws NullPointerException if the mapping function is null
*/
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return Optional.empty();
else {
return Optional.ofNullable(mapper.apply(getValue()));
}
}
/**
* If a value is present, apply the provided {@code Optional}-bearing
* mapping function to it, return that result, otherwise return an empty
* {@code Optional}. This method is similar to {@link #map(Function)},
* but the provided mapper is one whose result is already an {@code Optional},
* and if invoked, {@code flatMap} does not wrap it with an additional
* {@code Optional}.
*
* @param <U> The type parameter to the {@code Optional} returned by
* @param mapper a mapping function to apply to the mod object, if present
* the mapping function
* @return the result of applying an {@code Optional}-bearing mapping
* function to the value of this {@code Optional}, if a value is present,
* otherwise an empty {@code Optional}
* @throws NullPointerException if the mapping function is null or returns
* a null result
*/
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return Optional.empty();
else {
return Objects.requireNonNull(mapper.apply(getValue()));
}
}
/**
* Return the mod object if present, otherwise return {@code other}.
*
* @param other the mod object to be returned if there is no mod object present, may
* be null
* @return the mod object, if present, otherwise {@code other}
*/
public T orElse(T other) {
return getValue() != null ? getValue() : other;
}
/**
* Return the mod object if present, otherwise invoke {@code other} and return
* the result of that invocation.
*
* @param other a {@code Supplier} whose result is returned if no mod object
* is present
* @return the mod object if present otherwise the result of {@code other.get()}
* @throws NullPointerException if mod object is not present and {@code other} is
* null
*/
public T orElseGet(Supplier<? extends T> other) {
return getValue() != null ? getValue() : other.get();
}
/**
* Return the contained mod object, if present, otherwise throw an exception
* to be created by the provided supplier.
*
* @apiNote A method reference to the exception constructor with an empty
* argument list can be used as the supplier. For example,
* {@code IllegalStateException::new}
*
* @param <X> Type of the exception to be thrown
* @param exceptionSupplier The supplier which will return the exception to
* be thrown
* @return the present mod object
* @throws X if there is no mod object present
* @throws NullPointerException if no mod object is present and
* {@code exceptionSupplier} is null
*/
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (getValue() != null) {
return getValue();
} else {
throw exceptionSupplier.get();
}
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj instanceof OptionalMod) {
return Objects.equals(((OptionalMod)obj).modId, modId);
}
return false;
}
@Override
public int hashCode()
{
return Objects.hashCode(modId);
}
}

View file

@ -0,0 +1,247 @@
/*
* 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.minecraft.util.ResourceLocation;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.IForgeRegistryEntry;
import net.minecraftforge.registries.RegistryManager;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
public final class RegistryObject<T extends IForgeRegistryEntry<? super T>>
{
private final String name;
private final IForgeRegistry<?> owningRegistry;
private T value;
private boolean searched;
public static <T extends IForgeRegistryEntry<T>, U extends T> RegistryObject<U> of(final String name, Supplier<Class<T>> registryType) {
return new RegistryObject<>(name, registryType);
}
private static RegistryObject<?> EMPTY = new RegistryObject<>();
private static <T extends IForgeRegistryEntry<? super T>> RegistryObject<T> empty() {
@SuppressWarnings("unchecked")
RegistryObject<T> t = (RegistryObject<T>) EMPTY;
return t;
}
private RegistryObject() {
this.searched = true;
this.name = "";
this.owningRegistry = null;
}
private <V extends IForgeRegistryEntry<V>> RegistryObject(String name, Supplier<Class<V>> registryType)
{
this.name = name;
IForgeRegistry<V> registry;
try {
registry = RegistryManager.ACTIVE.getRegistry(registryType.get());
} catch (Throwable t) {
registry = null;
}
this.owningRegistry = registry;
}
private T getValue()
{
if (!searched) {
if (this.owningRegistry != null) {
//noinspection unchecked
this.value = (T)this.owningRegistry.getValue(new ResourceLocation(this.name));
}
searched = true;
}
return this.value;
}
public String getName() {
return this.name;
}
public Stream<T> stream() {
return isPresent() ? Stream.of(getValue()) : Stream.of();
}
/**
* Return {@code true} if there is a mod object present, otherwise {@code false}.
*
* @return {@code true} if there is a mod object present, otherwise {@code false}
*/
public boolean isPresent() {
return getValue() != null;
}
/**
* If a mod object is present, invoke the specified consumer with the object,
* otherwise do nothing.
*
* @param consumer block to be executed if a mod object is present
* @throws NullPointerException if mod object is present and {@code consumer} is
* null
*/
public void ifPresent(Consumer<? super T> consumer) {
if (getValue() != null)
consumer.accept(getValue());
}
/**
* If a mod object is present, and the mod object matches the given predicate,
* return an {@code RegistryObject} describing the value, otherwise return an
* empty {@code RegistryObject}.
*
* @param predicate a predicate to apply to the mod object, if present
* @return an {@code RegistryObject} describing the value of this {@code RegistryObject}
* if a mod object is present and the mod object matches the given predicate,
* otherwise an empty {@code RegistryObject}
* @throws NullPointerException if the predicate is null
*/
public RegistryObject<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(getValue()) ? this : empty();
}
/**
* If a mod object is present, apply the provided mapping function to it,
* and if the result is non-null, return an {@code Optional} describing the
* result. Otherwise return an empty {@code Optional}.
*
* @apiNote This method supports post-processing on optional values, without
* the need to explicitly check for a return status.
*
* @param <U> The type of the result of the mapping function
* @param mapper a mapping function to apply to the mod object, if present
* @return an {@code Optional} describing the result of applying a mapping
* function to the mod object of this {@code RegistryObject}, if a mod object is present,
* otherwise an empty {@code Optional}
* @throws NullPointerException if the mapping function is null
*/
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return Optional.empty();
else {
return Optional.ofNullable(mapper.apply(getValue()));
}
}
/**
* If a value is present, apply the provided {@code Optional}-bearing
* mapping function to it, return that result, otherwise return an empty
* {@code Optional}. This method is similar to {@link #map(Function)},
* but the provided mapper is one whose result is already an {@code Optional},
* and if invoked, {@code flatMap} does not wrap it with an additional
* {@code Optional}.
*
* @param <U> The type parameter to the {@code Optional} returned by
* @param mapper a mapping function to apply to the mod object, if present
* the mapping function
* @return the result of applying an {@code Optional}-bearing mapping
* function to the value of this {@code Optional}, if a value is present,
* otherwise an empty {@code Optional}
* @throws NullPointerException if the mapping function is null or returns
* a null result
*/
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return Optional.empty();
else {
return Objects.requireNonNull(mapper.apply(getValue()));
}
}
/**
* Return the mod object if present, otherwise return {@code other}.
*
* @param other the mod object to be returned if there is no mod object present, may
* be null
* @return the mod object, if present, otherwise {@code other}
*/
public T orElse(T other) {
return getValue() != null ? getValue() : other;
}
/**
* Return the mod object if present, otherwise invoke {@code other} and return
* the result of that invocation.
*
* @param other a {@code Supplier} whose result is returned if no mod object
* is present
* @return the mod object if present otherwise the result of {@code other.get()}
* @throws NullPointerException if mod object is not present and {@code other} is
* null
*/
public T orElseGet(Supplier<? extends T> other) {
return getValue() != null ? getValue() : other.get();
}
/**
* Return the contained mod object, if present, otherwise throw an exception
* to be created by the provided supplier.
*
* @apiNote A method reference to the exception constructor with an empty
* argument list can be used as the supplier. For example,
* {@code IllegalStateException::new}
*
* @param <X> Type of the exception to be thrown
* @param exceptionSupplier The supplier which will return the exception to
* be thrown
* @return the present mod object
* @throws X if there is no mod object present
* @throws NullPointerException if no mod object is present and
* {@code exceptionSupplier} is null
*/
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (getValue() != null) {
return getValue();
} else {
throw exceptionSupplier.get();
}
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj instanceof RegistryObject) {
return Objects.equals(((RegistryObject)obj).name, name);
}
return false;
}
@Override
public int hashCode()
{
return Objects.hashCode(name);
}
}

View file

@ -22,14 +22,23 @@ package net.minecraftforge.fml;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraftforge.api.Side; import net.minecraftforge.api.Side;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.client.SplashProgress;
import net.minecraftforge.fml.common.event.FMLClientInitEvent;
import net.minecraftforge.fml.common.event.FMLServerInitEvent;
import net.minecraftforge.fml.loading.FMLEnvironment; import net.minecraftforge.fml.loading.FMLEnvironment;
import sun.plugin.security.StripClassFile;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
public enum SidedProvider public enum SidedProvider
{ {
DATAFIXER(c->c.get().getDataFixer(), s->s.get().getDataFixer()); DATAFIXER(c->c.get().getDataFixer(), s->s.get().getDataFixer()),
SIDEDINIT((Function<Supplier<Minecraft>, Function<ModContainer, Event>>)c-> mc->new FMLClientInitEvent(c.get(), mc),
(Function<Supplier<DedicatedServer>, Function<ModContainer, Event>>)s-> mc->new FMLServerInitEvent(s.get(), mc)),
STRIPCHARS((Function<Supplier<Minecraft>, Function<String, String>>)c-> SplashProgress::stripSpecialChars,
(Function<Supplier<DedicatedServer>, Function<String, String>>)s-> str->str);
private static Supplier<Minecraft> client; private static Supplier<Minecraft> client;
private static Supplier<DedicatedServer> server; private static Supplier<DedicatedServer> server;

View file

@ -22,10 +22,13 @@ package net.minecraftforge.fml.client;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.minecraftforge.common.ForgeVersion; import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.fml.ModList;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream; import java.util.stream.Stream;
public class BrandingControl public class BrandingControl
@ -41,7 +44,7 @@ public class BrandingControl
brd.add("Minecraft " + ForgeVersion.mcVersion); brd.add("Minecraft " + ForgeVersion.mcVersion);
brd.add("MCP " + ForgeVersion.mcpVersion); brd.add("MCP " + ForgeVersion.mcpVersion);
brd.add("Forge " + ForgeVersion.getVersion()); brd.add("Forge " + ForgeVersion.getVersion());
int tModCount = 2; int tModCount = ModList.get().size();
brd.add(MessageFormat.format("{0,choice,0#No mods|1#1 mod|1<{0} mods} loaded", tModCount)); brd.add(MessageFormat.format("{0,choice,0#No mods|1#1 mod|1<{0} mods} loaded", tModCount));
brandings = brd.build(); brandings = brd.build();
@ -59,6 +62,10 @@ public class BrandingControl
} }
} }
public static void forEachLine(boolean includeMC, boolean reverse, BiConsumer<Integer, String> lineConsumer) {
final List<String> brandings = getBrandings(includeMC, reverse);
IntStream.range(0, brandings.size()).boxed().forEachOrdered(idx -> lineConsumer.accept(idx, brandings.get(idx)));
}
private static final List<String> defaultClientBranding = Stream.of("fml", "forge").collect(Collectors.toList()); private static final List<String> defaultClientBranding = Stream.of("fml", "forge").collect(Collectors.toList());
public static String getClientBranding() { public static String getClientBranding() {
return defaultClientBranding.stream().collect(Collectors.joining(",")); return defaultClientBranding.stream().collect(Collectors.joining(","));

View file

@ -25,16 +25,24 @@ import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.resources.IReloadableResourceManager; import net.minecraft.client.resources.IReloadableResourceManager;
import net.minecraft.client.resources.IResourcePack; import net.minecraft.client.resources.IResourcePack;
import net.minecraft.client.resources.data.MetadataSerializer; import net.minecraft.client.resources.data.MetadataSerializer;
import net.minecraftforge.api.Side;
import net.minecraftforge.api.SideOnly;
import net.minecraftforge.fml.SidedProvider; import net.minecraftforge.fml.SidedProvider;
import net.minecraftforge.fml.VersionChecker; import net.minecraftforge.fml.VersionChecker;
import net.minecraftforge.fml.ModLoader; import net.minecraftforge.fml.ModLoader;
import net.minecraftforge.fml.client.gui.GuiNotification;
import net.minecraftforge.fml.client.registry.RenderingRegistry;
import org.lwjgl.input.Mouse; import org.lwjgl.input.Mouse;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@SideOnly(Side.CLIENT)
public class ClientModLoader public class ClientModLoader
{ {
private static boolean loading;
private static Minecraft mc;
/** /**
* Mod loading entrypoint for the client * Mod loading entrypoint for the client
* @param minecraft * @param minecraft
@ -44,6 +52,8 @@ public class ClientModLoader
*/ */
public static void begin(final Minecraft minecraft, final List<IResourcePack> defaultResourcePacks, final IReloadableResourceManager mcResourceManager, MetadataSerializer metadataSerializer_) public static void begin(final Minecraft minecraft, final List<IResourcePack> defaultResourcePacks, final IReloadableResourceManager mcResourceManager, MetadataSerializer metadataSerializer_)
{ {
loading = true;
ClientModLoader.mc = minecraft;
SidedProvider.setClient(()->minecraft); SidedProvider.setClient(()->minecraft);
SplashProgress.start(); SplashProgress.start();
ModLoader.get().loadMods(); ModLoader.get().loadMods();
@ -52,6 +62,9 @@ public class ClientModLoader
public static void end() public static void end()
{ {
ModLoader.get().finishMods();
loading = false;
mc.gameSettings.loadOptions();
SplashProgress.finish(); SplashProgress.finish();
} }
@ -91,4 +104,9 @@ public class ClientModLoader
{ {
return false; return false;
} }
public static boolean isLoading()
{
return loading;
}
} }

View file

@ -22,7 +22,7 @@ package net.minecraftforge.fml.client;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.language.ExtensionPoint; import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo; import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import java.util.Optional; import java.util.Optional;

View file

@ -89,7 +89,18 @@ import net.minecraftforge.client.resource.SelectiveReloadStateHandler;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.ConfigManager; import net.minecraftforge.common.config.ConfigManager;
import net.minecraftforge.common.util.CompoundDataFixer; import net.minecraftforge.common.util.CompoundDataFixer;
import net.minecraftforge.fml.client.gui.CustomModLoadingErrorDisplayException;
import net.minecraftforge.fml.client.gui.GuiAccessDenied;
import net.minecraftforge.fml.client.gui.GuiConfirmation;
import net.minecraftforge.fml.client.gui.GuiCustomModLoadingErrorScreen;
import net.minecraftforge.fml.client.gui.GuiDupesFound;
import net.minecraftforge.fml.client.gui.GuiModList; import net.minecraftforge.fml.client.gui.GuiModList;
import net.minecraftforge.fml.client.gui.GuiModsMissing;
import net.minecraftforge.fml.client.gui.GuiMultipleModsErrored;
import net.minecraftforge.fml.client.gui.GuiNotification;
import net.minecraftforge.fml.client.gui.GuiOldSaveLoadConfirm;
import net.minecraftforge.fml.client.gui.GuiSortingProblem;
import net.minecraftforge.fml.client.gui.GuiWrongMinecraft;
import net.minecraftforge.fml.client.registry.RenderingRegistry; import net.minecraftforge.fml.client.registry.RenderingRegistry;
import net.minecraftforge.fml.common.DummyModContainer; import net.minecraftforge.fml.common.DummyModContainer;
import net.minecraftforge.fml.common.DuplicateModsFoundException; import net.minecraftforge.fml.common.DuplicateModsFoundException;
@ -166,8 +177,6 @@ public class FMLClientHandler implements IFMLSidedHandler
*/ */
private Minecraft client; private Minecraft client;
private DummyModContainer optifineContainer;
private boolean loading = true; private boolean loading = true;
@Nullable @Nullable

View file

@ -49,6 +49,7 @@ import javax.imageio.ImageIO;
import javax.imageio.ImageReader; import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageInputStream;
import com.google.common.base.CharMatcher;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.GlStateManager;
@ -744,6 +745,17 @@ public class SplashProgress
private static final IntBuffer buf = BufferUtils.createIntBuffer(4 * 1024 * 1024); private static final IntBuffer buf = BufferUtils.createIntBuffer(4 * 1024 * 1024);
// From FontRenderer.renderCharAtPos
private static final String ALLOWED_CHARS = "\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000";
private static final CharMatcher DISALLOWED_CHAR_MATCHER = CharMatcher.anyOf(ALLOWED_CHARS).negate();
public static String stripSpecialChars(String message)
{
// We can't handle many unicode points in the splash renderer
return DISALLOWED_CHAR_MATCHER.removeFrom(net.minecraft.util.StringUtils.stripControlCodes(message));
}
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static class Texture private static class Texture
{ {

View file

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.client; package net.minecraftforge.fml.client.gui;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiErrorScreen; import net.minecraft.client.gui.GuiErrorScreen;

View file

@ -17,12 +17,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.client; package net.minecraftforge.fml.client.gui;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.multiplayer.ServerData; import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraftforge.fml.client.FMLClientHandler;
public class GuiAccessDenied extends GuiScreen public class GuiAccessDenied extends GuiScreen
{ {

View file

@ -17,12 +17,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.client; package net.minecraftforge.fml.client.gui;
import java.io.File; import java.io.File;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraftforge.fml.client.FMLClientHandler;
public class GuiBackupFailed extends GuiScreen public class GuiBackupFailed extends GuiScreen
{ {

View file

@ -17,11 +17,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.client; package net.minecraftforge.fml.client.gui;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiOptionButton; import net.minecraft.client.gui.GuiOptionButton;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.StartupQuery; import net.minecraftforge.fml.common.StartupQuery;
public class GuiConfirmation extends GuiNotification public class GuiConfirmation extends GuiNotification

View file

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.client; package net.minecraftforge.fml.client.gui;
public class GuiCustomModLoadingErrorScreen extends GuiErrorBase public class GuiCustomModLoadingErrorScreen extends GuiErrorBase
{ {

View file

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.client; package net.minecraftforge.fml.client.gui;
import net.minecraftforge.fml.common.DuplicateModsFoundException; import net.minecraftforge.fml.common.DuplicateModsFoundException;
import net.minecraftforge.fml.ModContainer; import net.minecraftforge.fml.ModContainer;

View file

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.client; package net.minecraftforge.fml.client.gui;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiErrorScreen; import net.minecraft.client.gui.GuiErrorScreen;

View file

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.client; package net.minecraftforge.fml.client.gui;
import java.util.List; import java.util.List;

View file

@ -17,13 +17,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.client; package net.minecraftforge.fml.client.gui;
import java.util.List; import java.util.List;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.MissingModsException; import net.minecraftforge.fml.common.MissingModsException;
import net.minecraftforge.fml.common.versioning.ArtifactVersion; import net.minecraftforge.fml.common.versioning.ArtifactVersion;

View file

@ -17,14 +17,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.client; package net.minecraftforge.fml.client.gui;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.client.gui.GuiScrollingList;
import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.MissingModsException; import net.minecraftforge.fml.common.MissingModsException;
import net.minecraftforge.fml.common.ModContainer; import net.minecraftforge.fml.common.ModContainer;

View file

@ -17,11 +17,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.client; package net.minecraftforge.fml.client.gui;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.StartupQuery; import net.minecraftforge.fml.common.StartupQuery;
public class GuiNotification extends GuiScreen public class GuiNotification extends GuiScreen

View file

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.client; package net.minecraftforge.fml.client.gui;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -26,6 +26,7 @@ import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiYesNo; import net.minecraft.client.gui.GuiYesNo;
import net.minecraft.client.gui.GuiYesNoCallback; import net.minecraft.client.gui.GuiYesNoCallback;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.FMLLog; import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.StartupQuery; import net.minecraftforge.fml.common.StartupQuery;
import net.minecraftforge.fml.common.ZipperUtil; import net.minecraftforge.fml.common.ZipperUtil;

View file

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.client; package net.minecraftforge.fml.client.gui;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.fml.ModContainer; import net.minecraftforge.fml.ModContainer;

View file

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
package net.minecraftforge.fml.client; package net.minecraftforge.fml.client.gui;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;

View file

@ -32,26 +32,6 @@ public class RenderingRegistry
private static final RenderingRegistry INSTANCE = new RenderingRegistry(); private static final RenderingRegistry INSTANCE = new RenderingRegistry();
private Map<Class<? extends Entity>, IRenderFactory<? extends Entity>> entityRenderers = Maps.newHashMap(); private Map<Class<? extends Entity>, IRenderFactory<? extends Entity>> entityRenderers = Maps.newHashMap();
private Map<Class<? extends Entity>, Render<? extends Entity>> entityRenderersOld = Maps.newHashMap();
/**
* Register an entity rendering handler. This will, after mod initialization, be inserted into the main
* render map for entities.
* Call this during Initialization phase.
*
* @deprecated use the factory version during Preinitialization.
* TODO Will be removed in 1.11.
*/
@Deprecated
public static void registerEntityRenderingHandler(Class<? extends Entity> entityClass, Render<? extends Entity> renderer)
{
INSTANCE.entityRenderersOld.put(entityClass, renderer);
}
public static void loadEntityRenderers(Map<Class<? extends Entity>, Render<? extends Entity>> entityRenderMap)
{
entityRenderMap.putAll(INSTANCE.entityRenderersOld);
}
/** /**
* Register an entity rendering handler. This will, after mod initialization, be inserted into the main * Register an entity rendering handler. This will, after mod initialization, be inserted into the main
@ -63,16 +43,13 @@ public class RenderingRegistry
INSTANCE.entityRenderers.put(entityClass, renderFactory); INSTANCE.entityRenderers.put(entityClass, renderFactory);
} }
public static void loadEntityRenderers(RenderManager manager, Map<Class<? extends Entity> , Render<? extends Entity>> renderMap) public static void loadEntityRenderers(RenderManager manager, Map<Class<? extends Entity>, Render<? extends Entity>> renderMap)
{ {
for (Map.Entry<Class<? extends Entity>, IRenderFactory<? extends Entity>> entry : INSTANCE.entityRenderers.entrySet()) INSTANCE.entityRenderers.forEach((key, value) -> register(manager, renderMap, key, value));
{
register(manager, renderMap, entry.getKey(), entry.getValue());
}
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static <T extends Entity> void register(RenderManager manager, Map<Class<? extends Entity> , Render<? extends Entity>> renderMap, Class<T> entityClass, IRenderFactory<?> renderFactory) private static <T extends Entity> void register(RenderManager manager, Map<Class<? extends Entity>, Render<? extends Entity>> renderMap, Class<T> entityClass, IRenderFactory<?> renderFactory)
{ {
renderMap.put(entityClass, ((IRenderFactory<T>)renderFactory).createRenderFor(manager)); renderMap.put(entityClass, ((IRenderFactory<T>)renderFactory).createRenderFor(manager));
} }

View file

@ -19,18 +19,18 @@
package net.minecraftforge.fml.common; package net.minecraftforge.fml.common;
import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.google.common.base.Joiner;
import net.minecraftforge.api.Side; import net.minecraftforge.api.Side;
import net.minecraftforge.fml.SidedExecutor; import net.minecraftforge.fml.SidedExecutor;
import net.minecraftforge.fml.SidedProvider;
import net.minecraftforge.fml.client.SplashProgress; import net.minecraftforge.fml.client.SplashProgress;
import org.apache.logging.log4j.message.MessageFormatMessage; import org.apache.logging.log4j.message.MessageFormatMessage;
import org.apache.logging.log4j.message.StringFormattedMessage;
import org.lwjgl.LWJGLUtil;
import org.lwjgl.opengl.Display;
import static net.minecraftforge.fml.Logging.SPLASH; import static net.minecraftforge.fml.Logging.SPLASH;
import static net.minecraftforge.fml.Logging.fmlLog; import static net.minecraftforge.fml.Logging.fmlLog;
@ -121,7 +121,7 @@ public class ProgressManager
public void step(Class<?> classToName, String... extra) public void step(Class<?> classToName, String... extra)
{ {
step(ClassNameUtils.shortName(classToName)+Joiner.on(' ').join(extra)); step(ClassNameUtils.shortName(classToName)+ Arrays.stream(extra).collect(Collectors.joining(" ")));
} }
public void step(String message) public void step(String message)
@ -133,9 +133,8 @@ public class ProgressManager
fmlLog.debug(SPLASH,new MessageFormatMessage("Bar Step: {0} - {1} took {2,number,0.000}ms", getTitle(), getMessage(), (newTime - lastTime) / 1.0e6)); fmlLog.debug(SPLASH,new MessageFormatMessage("Bar Step: {0} - {1} took {2,number,0.000}ms", getTitle(), getMessage(), (newTime - lastTime) / 1.0e6));
lastTime = newTime; lastTime = newTime;
} }
step++; step += 1;
this.message = FMLCommonHandler.instance().stripSpecialChars(message); this.message = SidedProvider.STRIPCHARS.<Function<String, String>>get().apply(message);
FMLCommonHandler.instance().processWindowMessages();
} }
public String getTitle() public String getTitle()

View file

@ -0,0 +1,31 @@
/*
* 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.common.event;
import net.minecraft.client.Minecraft;
import net.minecraftforge.fml.ModContainer;
public class FMLClientInitEvent extends ModLifecycleEvent
{
public FMLClientInitEvent(Minecraft mc, ModContainer container)
{
super(container);
}
}

View file

@ -0,0 +1,31 @@
/*
* 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.common.event;
import net.minecraft.server.MinecraftServer;
import net.minecraftforge.fml.ModContainer;
public class FMLServerInitEvent extends ModLifecycleEvent
{
public FMLServerInitEvent(MinecraftServer server, ModContainer container)
{
super(container);
}
}

View file

@ -19,6 +19,8 @@
package net.minecraftforge.fml.javafmlmod; package net.minecraftforge.fml.javafmlmod;
import net.minecraftforge.fml.DeferredWorkQueue;
import net.minecraftforge.fml.LifecycleEventProvider;
import net.minecraftforge.fml.language.IModLanguageProvider; import net.minecraftforge.fml.language.IModLanguageProvider;
import net.minecraftforge.fml.language.IModInfo; import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.language.ModFileScanData; import net.minecraftforge.fml.language.ModFileScanData;
@ -29,6 +31,7 @@ import org.objectweb.asm.Type;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.Map; import java.util.Map;
import java.util.concurrent.FutureTask;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -59,6 +62,9 @@ public class FMLJavaModLanguageProvider implements IModLanguageProvider
@Override @Override
public <T> T loadMod(final IModInfo info, final ClassLoader modClassLoader, final ModFileScanData modFileScanResults) public <T> T loadMod(final IModInfo info, final ClassLoader modClassLoader, final ModFileScanData modFileScanResults)
{ {
// This language class is loaded in the system level classloader - before the game even starts
// So we must treat container construction as an arms length operation, and load the container
// in the classloader of the game - the context classloader is appropriate here.
try try
{ {
final Constructor<?> constructor = Class.forName("net.minecraftforge.fml.javafmlmod.FMLModContainer", true, Thread.currentThread().getContextClassLoader()). final Constructor<?> constructor = Class.forName("net.minecraftforge.fml.javafmlmod.FMLModContainer", true, Thread.currentThread().getContextClassLoader()).
@ -92,4 +98,14 @@ public class FMLJavaModLanguageProvider implements IModLanguageProvider
scanResult.addLanguageLoader(modTargetMap); scanResult.addLanguageLoader(modTargetMap);
}; };
} }
@Override
public void preLifecycleEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent)
{
}
@Override
public void postLifecycleEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent)
{
}
} }

View file

@ -49,9 +49,12 @@ public class FMLModContainer extends ModContainer
{ {
super(info); super(info);
this.scanResults = modFileScanResults; this.scanResults = modFileScanResults;
triggerMap.put(ModLoadingStage.BEGIN, dummy().andThen(this::beforeEvent).andThen(this::constructMod).andThen(this::afterEvent)); triggerMap.put(ModLoadingStage.CONSTRUCT, 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::preinitMod).andThen(this::fireEvent).andThen(this::afterEvent));
triggerMap.put(ModLoadingStage.PREINIT, dummy().andThen(this::beforeEvent).andThen(this::initMod).andThen(this::fireEvent).andThen(this::afterEvent)); triggerMap.put(ModLoadingStage.SIDEDINIT, dummy().andThen(this::beforeEvent).andThen(this::fireEvent).andThen(this::afterEvent));
triggerMap.put(ModLoadingStage.INIT, dummy().andThen(this::beforeEvent).andThen(this::initMod).andThen(this::fireEvent).andThen(this::afterEvent));
triggerMap.put(ModLoadingStage.POSTINIT, dummy().andThen(this::beforeEvent).andThen(this::fireEvent).andThen(this::afterEvent));
triggerMap.put(ModLoadingStage.COMPLETE, dummy().andThen(this::beforeEvent).andThen(this::completeLoading).andThen(this::fireEvent).andThen(this::afterEvent));
this.eventBus = IEventBus.create(this::onEventFailed); this.eventBus = IEventBus.create(this::onEventFailed);
try try
@ -66,6 +69,11 @@ public class FMLModContainer extends ModContainer
} }
} }
private void completeLoading(LifecycleEventProvider.LifecycleEvent lifecycleEvent)
{
}
private void initMod(LifecycleEventProvider.LifecycleEvent lifecycleEvent) private void initMod(LifecycleEventProvider.LifecycleEvent lifecycleEvent)
{ {

View file

@ -20,8 +20,11 @@
package net.minecraftforge.fml.javafmlmod; package net.minecraftforge.fml.javafmlmod;
import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.language.ExtensionPoint; import net.minecraftforge.fml.DeferredWorkQueue;
import net.minecraftforge.fml.ExtensionPoint;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.function.Supplier; import java.util.function.Supplier;
public class ModLoadingContext public class ModLoadingContext

View file

@ -19,6 +19,8 @@
package net.minecraftforge.fml.language; package net.minecraftforge.fml.language;
import net.minecraftforge.fml.LifecycleEventProvider;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
@ -33,6 +35,9 @@ public interface IModLanguageProvider
Consumer<ModFileScanData> getFileVisitor(); Consumer<ModFileScanData> getFileVisitor();
void preLifecycleEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent);
void postLifecycleEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent);
interface IModLanguageLoader { interface IModLanguageLoader {
<T> T loadMod(IModInfo info, ClassLoader modClassLoader, ModFileScanData modFileScanResults); <T> T loadMod(IModInfo info, ClassLoader modClassLoader, ModFileScanData modFileScanResults);
} }

View file

@ -32,6 +32,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.function.Consumer;
import java.util.stream.Stream; import java.util.stream.Stream;
import static net.minecraftforge.fml.Logging.CORE; import static net.minecraftforge.fml.Logging.CORE;
@ -43,6 +44,11 @@ public class LanguageLoadingProvider
private final ServiceLoader<IModLanguageProvider> serviceLoader; private final ServiceLoader<IModLanguageProvider> serviceLoader;
private final Map<String, ModLanguageWrapper> languageProviderMap = new HashMap<>(); private final Map<String, ModLanguageWrapper> languageProviderMap = new HashMap<>();
public void forEach(final Consumer<IModLanguageProvider> consumer)
{
languageProviders.forEach(consumer);
}
private static class ModLanguageWrapper { private static class ModLanguageWrapper {
private final IModLanguageProvider modLanguageProvider; private final IModLanguageProvider modLanguageProvider;
private final ArtifactVersion version; private final ArtifactVersion version;

View file

@ -38,7 +38,8 @@ import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* Master list of all mods * Master list of all mods <em>in the loading context. This class cannot refer outside the
* loading package</em>
*/ */
public class LoadingModList public class LoadingModList
{ {
@ -47,8 +48,6 @@ public class LoadingModList
private final List<ModInfo> sortedList; private final List<ModInfo> sortedList;
private final Map<String, ModFileInfo> fileById; private final Map<String, ModFileInfo> fileById;
private BackgroundScanHandler scanner; private BackgroundScanHandler scanner;
private List<ModContainer> mods;
private Map<String, ModContainer> indexedMods;
private LoadingModList(final List<ModFile> modFiles, final List<ModInfo> sortedList) private LoadingModList(final List<ModFile> modFiles, final List<ModInfo> sortedList)
{ {
@ -106,30 +105,6 @@ public class LoadingModList
return this.fileById.get(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() public List<ModInfo> getMods()
{ {
return this.sortedList; return this.sortedList;

View file

@ -51,12 +51,15 @@ import net.minecraft.nbt.NBTTagString;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.RegistryEvent.MissingMappings; import net.minecraftforge.event.RegistryEvent.MissingMappings;
import net.minecraftforge.fml.common.FMLLog; import org.apache.logging.log4j.LogManager;
import net.minecraftforge.fml.common.InjectedModContainer; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRegistryInternal<V>, IForgeRegistryModifiable<V> public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRegistryInternal<V>, IForgeRegistryModifiable<V>
{ {
public static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("forge.debugRegistryEntries", "false")); public static Marker REGISTRIES = MarkerManager.getMarker("REGISTRIES");
private static Logger LOGGER = LogManager.getLogger("FML");
private final RegistryManager stage; private final RegistryManager stage;
private final BiMap<Integer, V> ids = HashBiMap.create(); private final BiMap<Integer, V> ids = HashBiMap.create();
private final BiMap<ResourceLocation, V> names = HashBiMap.create(); private final BiMap<ResourceLocation, V> names = HashBiMap.create();
@ -293,7 +296,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
V oldEntry = getRaw(key); V oldEntry = getRaw(key);
if (oldEntry == value) // already registered, return prev registration's id if (oldEntry == value) // already registered, return prev registration's id
{ {
FMLLog.bigWarning("Registry {}: The object {} has been registered twice for the same name {}.", this.superType.getSimpleName(), value, key); LOGGER.warn(REGISTRIES,"Registry {}: The object {} has been registered twice for the same name {}.", this.superType.getSimpleName(), value, key);
return this.getID(value); return this.getID(value);
} }
if (oldEntry != null) // duplicate name if (oldEntry != null) // duplicate name
@ -302,8 +305,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
throw new IllegalArgumentException(String.format("The name %s has been registered twice, for %s and %s.", key, getRaw(key), value)); throw new IllegalArgumentException(String.format("The name %s has been registered twice, for %s and %s.", key, getRaw(key), value));
if (owner == null) if (owner == null)
throw new IllegalStateException(String.format("Could not determine owner for the override on %s. Value: %s", key, value)); throw new IllegalStateException(String.format("Could not determine owner for the override on %s. Value: %s", key, value));
if (DEBUG) LOGGER.debug(REGISTRIES,"Registry {} Override: {} {} -> {}", this.superType.getSimpleName(), key, oldEntry, value);
FMLLog.log.debug("Registry {} Override: {} {} -> {}", this.superType.getSimpleName(), key, oldEntry, value);
idToUse = this.getID(oldEntry); idToUse = this.getID(oldEntry);
} }
@ -345,11 +347,10 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
if (this.add != null) if (this.add != null)
this.add.onAdd(this, this.stage, idToUse, value, oldEntry); this.add.onAdd(this, this.stage, idToUse, value, oldEntry);
if (this.dummies.remove(key) && DEBUG) if (this.dummies.remove(key))
FMLLog.log.debug("Registry {} Dummy Remove: {}", this.superType.getSimpleName(), key); LOGGER.debug(REGISTRIES,"Registry {} Dummy Remove: {}", this.superType.getSimpleName(), key);
if (DEBUG) LOGGER.trace(REGISTRIES,"Registry {} add: {} {} {} (req. id {})", this.superType.getSimpleName(), key, idToUse, value, id);
FMLLog.log.trace("Registry {} add: {} {} {} (req. id {})", this.superType.getSimpleName(), key, idToUse, value, id);
return idToUse; return idToUse;
} }
@ -377,8 +378,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
if (this.isLocked()) if (this.isLocked())
throw new IllegalStateException(String.format("Attempted to register the alias %s -> %s to late", from, to)); throw new IllegalStateException(String.format("Attempted to register the alias %s -> %s to late", from, to));
this.aliases.put(from, to); this.aliases.put(from, to);
if (DEBUG) LOGGER.trace(REGISTRIES,"Registry {} alias: {} -> {}", this.superType.getSimpleName(), from, to);
FMLLog.log.trace("Registry {} alias: {} -> {}", this.superType.getSimpleName(), from, to);
} }
void addDummy(ResourceLocation key) void addDummy(ResourceLocation key)
@ -386,8 +386,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
if (this.isLocked()) if (this.isLocked())
throw new IllegalStateException(String.format("Attempted to register the dummy %s to late", key)); throw new IllegalStateException(String.format("Attempted to register the dummy %s to late", key));
this.dummies.add(key); this.dummies.add(key);
if (DEBUG) LOGGER.trace(REGISTRIES,"Registry {} dummy: {}", this.superType.getSimpleName(), key);
FMLLog.log.trace("Registry {} dummy: {}", this.superType.getSimpleName(), key);
} }
private RegistryDelegate<V> getDelegate(V thing) private RegistryDelegate<V> getDelegate(V thing)
@ -471,8 +470,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
void sync(ResourceLocation name, ForgeRegistry<V> from) void sync(ResourceLocation name, ForgeRegistry<V> from)
{ {
if (DEBUG) LOGGER.debug(REGISTRIES,"Registry {} Sync: {} -> {}", this.superType.getSimpleName(), this.stage.getName(), from.stage.getName());
FMLLog.log.debug("Registry {} Sync: {} -> {}", this.superType.getSimpleName(), this.stage.getName(), from.stage.getName());
if (this == from) if (this == from)
throw new IllegalArgumentException("WTF We are the same!?!?!"); throw new IllegalArgumentException("WTF We are the same!?!?!");
if (from.superType != this.superType) if (from.superType != this.superType)
@ -509,7 +507,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
int realId = add(id, entry.getValue()); int realId = add(id, entry.getValue());
if (id != realId && id != -1) if (id != realId && id != -1)
{ {
FMLLog.log.warn("Registry {}: Object did not get ID it asked for. Name: {} Expected: {} Got: {}", this.superType.getSimpleName(), entry.getKey(), id, realId); LOGGER.warn(REGISTRIES,"Registry {}: Object did not get ID it asked for. Name: {} Expected: {} Got: {}", this.superType.getSimpleName(), entry.getKey(), id, realId);
errored = true; errored = true;
} }
} }
@ -521,14 +519,14 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
OverrideOwner owner = from.owners.inverse().get(value); OverrideOwner owner = from.owners.inverse().get(value);
if (owner == null) if (owner == null)
{ {
FMLLog.log.warn("Registry {}: Override did not have an associated owner object. Name: {} Value: {}", this.superType.getSimpleName(), entry.getKey(), value); LOGGER.warn(REGISTRIES,"Registry {}: Override did not have an associated owner object. Name: {} Value: {}", this.superType.getSimpleName(), entry.getKey(), value);
errored = true; errored = true;
continue; continue;
} }
int realId = add(id, value, owner.owner); int realId = add(id, value, owner.owner);
if (id != realId && id != -1) if (id != realId && id != -1)
{ {
FMLLog.log.warn("Registry {}: Object did not get ID it asked for. Name: {} Expected: {} Got: {}", this.superType.getSimpleName(), entry.getKey(), id, realId); LOGGER.warn(REGISTRIES,"Registry {}: Object did not get ID it asked for. Name: {} Expected: {} Got: {}", this.superType.getSimpleName(), entry.getKey(), id, realId);
errored = true; errored = true;
} }
} }
@ -582,8 +580,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
if (id == null) if (id == null)
throw new IllegalStateException("Removed a entry that did not have an associated id: " + key + " " + value.toString() + " This should never happen unless hackery!"); throw new IllegalStateException("Removed a entry that did not have an associated id: " + key + " " + value.toString() + " This should never happen unless hackery!");
if (DEBUG) LOGGER.trace(REGISTRIES,"Registry {} remove: {} {}", this.superType.getSimpleName(), key, id);
FMLLog.log.trace("Registry {} remove: {} {}", this.superType.getSimpleName(), key, id);
} }
return value; return value;
@ -627,8 +624,8 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
Collections.sort(ids); Collections.sort(ids);
FMLLog.log.trace("Registry Name : {}", name); LOGGER.trace(REGISTRIES, "Registry Name : {}", name);
ids.forEach(id -> FMLLog.log.trace(" Registry: {} {} {}", id, getKey(getValue(id)), getValue(id))); ids.forEach(id -> LOGGER.trace(REGISTRIES," Registry: {} {} {}", id, getKey(getValue(id)), getValue(id)));
} }
public void loadIds(Map<ResourceLocation, Integer> ids, Map<ResourceLocation, String> overrides, Map<ResourceLocation, Integer> missing, Map<ResourceLocation, Integer[]> remapped, ForgeRegistry<V> old, ResourceLocation name) public void loadIds(Map<ResourceLocation, Integer> ids, Map<ResourceLocation, String> overrides, Map<ResourceLocation, Integer> missing, Map<ResourceLocation, Integer[]> remapped, ForgeRegistry<V> old, ResourceLocation name)
@ -642,13 +639,13 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
if (currId == -1) if (currId == -1)
{ {
FMLLog.log.info("Registry {}: Found a missing id from the world {}", this.superType.getSimpleName(), itemName); LOGGER.info(REGISTRIES,"Registry {}: Found a missing id from the world {}", this.superType.getSimpleName(), itemName);
missing.put(itemName, newId); missing.put(itemName, newId);
continue; // no block/item -> nothing to add continue; // no block/item -> nothing to add
} }
else if (currId != newId) else if (currId != newId)
{ {
FMLLog.log.debug("Registry {}: Fixed {} id mismatch {}: {} (init) -> {} (map).", this.superType.getSimpleName(), name, itemName, currId, newId); LOGGER.debug(REGISTRIES,"Registry {}: Fixed {} id mismatch {}: {} (init) -> {} (map).", this.superType.getSimpleName(), name, itemName, currId, newId);
remapped.put(itemName, new Integer[] {currId, newId}); remapped.put(itemName, new Integer[] {currId, newId});
} }
@ -674,7 +671,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
OverrideOwner owner = old.owners.inverse().get(value); OverrideOwner owner = old.owners.inverse().get(value);
if (owner == null) if (owner == null)
{ {
FMLLog.log.warn("Registry {}: Override did not have an associated owner object. Name: {} Value: {}", this.superType.getSimpleName(), entry.getKey(), value); LOGGER.warn(REGISTRIES,"Registry {}: Override did not have an associated owner object. Name: {} Value: {}", this.superType.getSimpleName(), entry.getKey(), value);
continue; continue;
} }
@ -683,12 +680,12 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
int realId = add(newId, value, owner.owner); int realId = add(newId, value, owner.owner);
if (newId != realId) if (newId != realId)
FMLLog.log.warn("Registry {}: Object did not get ID it asked for. Name: {} Expected: {} Got: {}", this.superType.getSimpleName(), entry.getKey(), newId, realId); LOGGER.warn(REGISTRIES,"Registry {}: Object did not get ID it asked for. Name: {} Expected: {} Got: {}", this.superType.getSimpleName(), entry.getKey(), newId, realId);
} }
int realId = add(newId, obj, primaryName == null ? itemName.getResourceDomain() : primaryName); int realId = add(newId, obj, primaryName == null ? itemName.getResourceDomain() : primaryName);
if (realId != newId) if (realId != newId)
FMLLog.log.warn("Registry {}: Object did not get ID it asked for. Name: {} Expected: {} Got: {}", this.superType.getSimpleName(), entry.getKey(), newId, realId); LOGGER.warn(REGISTRIES,"Registry {}: Object did not get ID it asked for. Name: {} Expected: {} Got: {}", this.superType.getSimpleName(), entry.getKey(), newId, realId);
ovs.remove(itemName); ovs.remove(itemName);
} }
@ -702,16 +699,16 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
V _new = this.owners.get(new OverrideOwner(owner, itemName)); V _new = this.owners.get(new OverrideOwner(owner, itemName));
if (_new == null) if (_new == null)
{ {
FMLLog.log.warn("Registry {}: Skipping override for {}, Unknown owner {}", this.superType.getSimpleName(), itemName, owner); LOGGER.warn(REGISTRIES,"Registry {}: Skipping override for {}, Unknown owner {}", this.superType.getSimpleName(), itemName, owner);
continue; continue;
} }
FMLLog.log.info("Registry {}: Activating override {} for {}", this.superType.getSimpleName(), owner, itemName); LOGGER.info(REGISTRIES,"Registry {}: Activating override {} for {}", this.superType.getSimpleName(), owner, itemName);
int newId = this.getID(itemName); int newId = this.getID(itemName);
int realId = this.add(newId, _new, owner); int realId = this.add(newId, _new, owner);
if (newId != realId) if (newId != realId)
FMLLog.log.warn("Registry {}: Object did not get ID it asked for. Name: {} Expected: {} Got: {}", this.superType.getSimpleName(), entry.getKey(), newId, realId); LOGGER.warn(REGISTRIES,"Registry {}: Object did not get ID it asked for. Name: {} Expected: {} Got: {}", this.superType.getSimpleName(), entry.getKey(), newId, realId);
} }
} }
} }
@ -722,8 +719,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
return false; return false;
V dummy = this.dummyFactory.createDummy(key); V dummy = this.dummyFactory.createDummy(key);
if (DEBUG) LOGGER.debug(REGISTRIES,"Registry Dummy Add: {} {} -> {}", key, id, dummy);
FMLLog.log.debug("Registry Dummy Add: {} {} -> {}", key, id, dummy);
//It was blocked before so we need to unset the blocking map //It was blocked before so we need to unset the blocking map
this.availabilityMap.clear(id); this.availabilityMap.clear(id);
@ -740,15 +736,14 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
throw new IllegalStateException("Removed a entry that did not have an associated id: " + key + " " + value.toString() + " This should never happen unless hackery!"); throw new IllegalStateException("Removed a entry that did not have an associated id: " + key + " " + value.toString() + " This should never happen unless hackery!");
if (oldid != id) if (oldid != id)
FMLLog.log.debug("Registry {}: Dummy ID mismatch {} {} -> {}", this.superType.getSimpleName(), key, oldid, id); LOGGER.debug(REGISTRIES,"Registry {}: Dummy ID mismatch {} {} -> {}", this.superType.getSimpleName(), key, oldid, id);
if (DEBUG) LOGGER.debug(REGISTRIES,"Registry {} remove: {} {}", this.superType.getSimpleName(), key, oldid);
FMLLog.log.debug("Registry {} remove: {} {}", this.superType.getSimpleName(), key, oldid);
} }
int realId = this.add(id, dummy); int realId = this.add(id, dummy);
if (realId != id) if (realId != id)
FMLLog.log.warn("Registry {}: Object did not get ID it asked for. Name: {} Expected: {} Got: {}", this.superType.getSimpleName(), key, id, realId); LOGGER.warn(REGISTRIES,"Registry {}: Object did not get ID it asked for. Name: {} Expected: {} Got: {}", this.superType.getSimpleName(), key, id, realId);
this.dummies.add(key); this.dummies.add(key);
return true; return true;
@ -773,8 +768,8 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
{ {
V obj = this.names.get(key); V obj = this.names.get(key);
OverrideOwner owner = this.owners.inverse().get(obj); OverrideOwner owner = this.owners.inverse().get(obj);
if (owner == null && DEBUG) if (owner == null)
FMLLog.log.debug("Registry {} {}: Invalid override {} {}", this.superType.getSimpleName(), this.stage.getName(), key, obj); LOGGER.debug(REGISTRIES,"Registry {} {}: Invalid override {} {}", this.superType.getSimpleName(), this.stage.getName(), key, obj);
ret.put(key, owner.owner); ret.put(key, owner.owner);
} }
return ret; return ret;
@ -904,7 +899,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
void processMissingEvent(ResourceLocation name, ForgeRegistry<V> pool, List<MissingMappings.Mapping<V>> mappings, Map<ResourceLocation, Integer> missing, Map<ResourceLocation, Integer[]> remaps, Collection<ResourceLocation> defaulted, Collection<ResourceLocation> failed, boolean injectNetworkDummies) void processMissingEvent(ResourceLocation name, ForgeRegistry<V> pool, List<MissingMappings.Mapping<V>> mappings, Map<ResourceLocation, Integer> missing, Map<ResourceLocation, Integer[]> remaps, Collection<ResourceLocation> defaulted, Collection<ResourceLocation> failed, boolean injectNetworkDummies)
{ {
FMLLog.log.debug("Processing missing event for {}:", name); LOGGER.debug(REGISTRIES,"Processing missing event for {}:", name);
int ignored = 0; int ignored = 0;
for (MissingMappings.Mapping<V> remap : mappings) for (MissingMappings.Mapping<V> remap : mappings)
@ -916,19 +911,19 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
// entry re-mapped, finish the registration with the new name/object, but the old id // entry re-mapped, finish the registration with the new name/object, but the old id
int currId = getID(remap.getTarget()); int currId = getID(remap.getTarget());
ResourceLocation newName = pool.getKey(remap.getTarget()); ResourceLocation newName = pool.getKey(remap.getTarget());
FMLLog.log.debug(" Remapping {} -> {}.", remap.key, newName); LOGGER.debug(REGISTRIES," Remapping {} -> {}.", remap.key, newName);
missing.remove(remap.key); missing.remove(remap.key);
//I don't think this will work, but I dont think it ever worked.. the item is already in the map with a different id... we want to fix that.. //I don't think this will work, but I dont think it ever worked.. the item is already in the map with a different id... we want to fix that..
int realId = this.add(remap.id, remap.getTarget()); int realId = this.add(remap.id, remap.getTarget());
if (realId != remap.id) if (realId != remap.id)
FMLLog.log.warn("Registered object did not get ID it asked for. Name: {} Type: {} Expected: {} Got: {}", newName, this.getRegistrySuperType(), remap.id, realId); LOGGER.warn(REGISTRIES,"Registered object did not get ID it asked for. Name: {} Type: {} Expected: {} Got: {}", newName, this.getRegistrySuperType(), remap.id, realId);
this.addAlias(remap.key, newName); this.addAlias(remap.key, newName);
if (currId != realId) if (currId != realId)
{ {
FMLLog.log.info(" Fixed id mismatch {}: {} (init) -> {} (map).", newName, currId, realId); LOGGER.info(REGISTRIES,"Fixed id mismatch {}: {} (init) -> {} (map).", newName, currId, realId);
remaps.put(newName, new Integer[] {currId, realId}); remaps.put(newName, new Integer[] {currId, realId});
} }
} }
@ -945,24 +940,24 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
} }
else if (action == MissingMappings.Action.IGNORE) else if (action == MissingMappings.Action.IGNORE)
{ {
FMLLog.log.debug(" Ignoring {}", remap.key); LOGGER.debug(REGISTRIES,"Ignoring {}", remap.key);
ignored++; ignored++;
} }
else if (action == MissingMappings.Action.FAIL) else if (action == MissingMappings.Action.FAIL)
{ {
FMLLog.log.debug(" Failing {}!", remap.key); LOGGER.debug(REGISTRIES,"Failing {}!", remap.key);
failed.add(remap.key); failed.add(remap.key);
} }
else if (action == MissingMappings.Action.WARN) else if (action == MissingMappings.Action.WARN)
{ {
FMLLog.log.warn(" {} may cause world breakage!", remap.key); LOGGER.warn(REGISTRIES,"{} may cause world breakage!", remap.key);
} }
this.block(remap.id); this.block(remap.id);
} }
} }
if (failed.isEmpty() && ignored > 0) if (failed.isEmpty() && ignored > 0)
FMLLog.log.debug("There were {} missing mappings that have been ignored", ignored); LOGGER.debug(REGISTRIES,"There were {} missing mappings that have been ignored", ignored);
} }
private static class OverrideOwner private static class OverrideOwner

View file

@ -83,6 +83,8 @@ import javax.annotation.Nullable;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import static net.minecraftforge.fml.Logging.fmlLog; import static net.minecraftforge.fml.Logging.fmlLog;
@ -116,6 +118,7 @@ public class GameData
private static final ResourceLocation BLOCK_TO_ITEM = new ResourceLocation("minecraft:blocktoitemmap"); private static final ResourceLocation BLOCK_TO_ITEM = new ResourceLocation("minecraft:blocktoitemmap");
private static final ResourceLocation BLOCKSTATE_TO_ID = new ResourceLocation("minecraft:blockstatetoid"); private static final ResourceLocation BLOCKSTATE_TO_ID = new ResourceLocation("minecraft:blockstatetoid");
private static final Logger LOGGER = LogManager.getLogger("FML");
private static boolean hasInit = false; private static boolean hasInit = false;
private static final boolean DISABLE_VANILLA_REGISTRIES = Boolean.parseBoolean(System.getProperty("forge.disableVanillaGameData", "false")); // Use for unit tests/debugging private static final boolean DISABLE_VANILLA_REGISTRIES = Boolean.parseBoolean(System.getProperty("forge.disableVanillaGameData", "false")); // Use for unit tests/debugging
private static final BiConsumer<ResourceLocation, ForgeRegistry<?>> LOCK_VANILLA = (name, reg) -> reg.slaves.values().stream().filter(o -> o instanceof ILockableRegistry).forEach(o -> ((ILockableRegistry)o).lock()); private static final BiConsumer<ResourceLocation, ForgeRegistry<?>> LOCK_VANILLA = (name, reg) -> reg.slaves.values().stream().filter(o -> o instanceof ILockableRegistry).forEach(o -> ((ILockableRegistry)o).lock());
@ -563,8 +566,7 @@ public class GameData
} }
else if (isLocalWorld) else if (isLocalWorld)
{ {
if (ForgeRegistry.DEBUG) LOGGER.debug("Registry {}: Resuscitating dummy entry {}", key, dummy);
FMLLog.log.debug("Registry {}: Resuscitating dummy entry {}", key, dummy);
} }
else else
{ {
@ -751,12 +753,10 @@ public class GameData
if (filter.test(BLOCKS)) if (filter.test(BLOCKS))
{ {
MinecraftForge.EVENT_BUS.post(RegistryManager.ACTIVE.getRegistry(BLOCKS).getRegisterEvent(BLOCKS)); MinecraftForge.EVENT_BUS.post(RegistryManager.ACTIVE.getRegistry(BLOCKS).getRegisterEvent(BLOCKS));
ObjectHolderRegistry.INSTANCE.applyObjectHolders(); // inject any blocks
} }
if (filter.test(ITEMS)) if (filter.test(ITEMS))
{ {
MinecraftForge.EVENT_BUS.post(RegistryManager.ACTIVE.getRegistry(ITEMS).getRegisterEvent(ITEMS)); MinecraftForge.EVENT_BUS.post(RegistryManager.ACTIVE.getRegistry(ITEMS).getRegisterEvent(ITEMS));
ObjectHolderRegistry.INSTANCE.applyObjectHolders(); // inject any items
} }
for (ResourceLocation rl : keys) for (ResourceLocation rl : keys)
{ {
@ -764,7 +764,6 @@ public class GameData
if (rl == BLOCKS || rl == ITEMS) continue; if (rl == BLOCKS || rl == ITEMS) continue;
MinecraftForge.EVENT_BUS.post(RegistryManager.ACTIVE.getRegistry(rl).getRegisterEvent(rl)); MinecraftForge.EVENT_BUS.post(RegistryManager.ACTIVE.getRegistry(rl).getRegisterEvent(rl));
} }
ObjectHolderRegistry.INSTANCE.applyObjectHolders(); // inject everything else
/* /*

View file

@ -25,7 +25,7 @@ import net.minecraft.item.Item;
import net.minecraftforge.client.event.ModelBakeEvent; import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.client.CustomModLoadingErrorDisplayException; import net.minecraftforge.fml.client.gui.CustomModLoadingErrorDisplayException;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent; import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent;