Some tweaks around the code base. A functional consumer for networking - return a bool from your consumer function, rather than setPacketHandled.

Tweak the server modloading behaviour to try and be a bit clearer that a mod errored.

Signed-off-by: cpw <cpw+github@weeksfamily.ca>
This commit is contained in:
cpw 2019-09-16 20:14:21 -04:00
parent 79ce18ac3e
commit 71a4828809
No known key found for this signature in database
GPG Key ID: 8EB3DF749553B1B7
7 changed files with 80 additions and 15 deletions

View File

@ -19,7 +19,9 @@
package net.minecraftforge.fml.loading;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Stream;
@ -40,4 +42,12 @@ public class Java9BackportUtils
downstream.combiner(), downstream.finisher(),
downstream.characteristics().toArray(new Collector.Characteristics[0]));
}
public static <T> void ifPresentOrElse(Optional<T> optional, Consumer<? super T> action, Runnable emptyAction) {
if (optional.isPresent()) {
action.accept(optional.get());
} else {
emptyAction.run();
}
}
}

View File

@ -144,20 +144,31 @@ public class ModSorter
private void buildUniqueList()
{
final Stream<ModInfo> modInfos = modFiles.stream().map(ModFile::getModInfos).flatMap(Collection::stream).map(ModInfo.class::cast);
final Stream<ModInfo> modInfos = modFiles.stream()
.map(ModFile::getModInfos)
.flatMap(Collection::stream)
.map(ModInfo.class::cast);
final Map<String, List<ModInfo>> modIds = modInfos.collect(Collectors.groupingBy(IModInfo::getModId));
// TODO: make this figure out dupe handling better
final List<Map.Entry<String, List<ModInfo>>> dupedMods = modIds.entrySet().stream().filter(e -> e.getValue().size() > 1).collect(Collectors.toList());
final List<Map.Entry<String, List<ModInfo>>> dupedMods = modIds
.entrySet()
.stream()
.filter(e -> e.getValue().size() > 1)
.collect(Collectors.toList());
if (!dupedMods.isEmpty()) {
final List<EarlyLoadingException.ExceptionData> duplicateModErrors = dupedMods.stream().
map(dm -> new EarlyLoadingException.ExceptionData("fml.modloading.dupedmod", dm.getValue().get(0))).
collect(Collectors.toList());
final List<EarlyLoadingException.ExceptionData> duplicateModErrors = dupedMods
.stream()
.map(dm -> new EarlyLoadingException.ExceptionData("fml.modloading.dupedmod", dm.getValue().get(0)))
.collect(Collectors.toList());
throw new EarlyLoadingException("Duplicate mods found", null, duplicateModErrors);
}
modIdNameLookup = modIds.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0)));
modIdNameLookup = modIds
.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0)));
}
private void verifyDependencyVersions()

View File

@ -45,8 +45,10 @@ public class Scanner {
result.addModFileInfo(fileToScan.getModFileInfo());
fileToScan.scanFile(p -> fileVisitor(p, result));
final IModLanguageProvider loader = fileToScan.getLoader();
LOGGER.debug(SCAN, "Scanning {} with language loader {}", fileToScan.getFilePath(), loader.name());
loader.getFileVisitor().accept(result);
if (loader != null) {
LOGGER.debug(SCAN, "Scanning {} with language loader {}", fileToScan.getFilePath(), loader.name());
loader.getFileVisitor().accept(result);
}
return result;
}

View File

@ -60,6 +60,7 @@ import net.minecraft.world.dimension.DimensionType;
import net.minecraftforge.event.world.RegisterDimensionsEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.StartupQuery;
import net.minecraftforge.fml.server.ServerModLoader;
import net.minecraftforge.registries.ClearableRegistry;
import net.minecraftforge.registries.ForgeRegistries;
@ -160,6 +161,9 @@ public class DimensionManager
Validate.notNull(server, "Must provide server when creating world");
Validate.notNull(dim, "Dimension type must not be null");
if (ServerModLoader.hasErrors()) {
throw new RuntimeException("The server has failed to initialize correctly due to mod loading errors. Examine the crash report for more details.");
}
// If we're in the early stages of loading, we need to return null so CommandSource can work properly for command function
if (StartupQuery.pendingQuery()) {
return null;

View File

@ -20,6 +20,7 @@
package net.minecraftforge.fml;
import java.util.List;
import java.util.stream.Collectors;
public class LoadingFailedException extends RuntimeException {
private final List<ModLoadingException> loadingExceptions;
@ -31,4 +32,9 @@ public class LoadingFailedException extends RuntimeException {
public List<ModLoadingException> getErrors() {
return this.loadingExceptions;
}
@Override
public String getMessage() {
return "Loading errors encountered: " + this.loadingExceptions.stream().map(ModLoadingException::getMessage).collect(Collectors.joining(",\n\t", "[\n\t", "\n]"));
}
}

View File

@ -182,6 +182,23 @@ public class SimpleChannel
return this;
}
public interface ToBooleanBiFunction<T, U> {
boolean applyAsBool(T first, U second);
}
/**
* Function returning a boolean "packet handled" indication, for simpler channel building.
* @param handler a handler
* @return this
*/
public MessageBuilder<MSG> consumer(ToBooleanBiFunction<MSG, Supplier<NetworkEvent.Context>> handler) {
this.consumer = (msg, ctx) -> {
boolean handled = handler.applyAsBool(msg, ctx);
ctx.get().setPacketHandled(handled);
};
return this;
}
public void add() {
final IndexedMessageCodec.MessageHandler<MSG> message = this.channel.registerMessage(this.id, this.type, this.encoder, this.decoder, this.consumer);
if (this.loginIndexSetter != null) {

View File

@ -21,10 +21,7 @@ package net.minecraftforge.fml.server;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.LogicalSidedProvider;
import net.minecraftforge.fml.ModLoader;
import net.minecraftforge.fml.ModLoadingWarning;
import net.minecraftforge.fml.SidedProvider;
import net.minecraftforge.fml.*;
import net.minecraftforge.fml.network.FMLStatusPing;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -37,17 +34,31 @@ public class ServerModLoader
{
private static final Logger LOGGER = LogManager.getLogger();
private static DedicatedServer server;
private static boolean hasErrors = false;
public static void begin(DedicatedServer dedicatedServer) {
ServerModLoader.server = dedicatedServer;
SidedProvider.setServer(()->dedicatedServer);
LogicalSidedProvider.setServer(()->dedicatedServer);
LanguageHook.loadForgeAndMCLangs();
ModLoader.get().gatherAndInitializeMods(null);
ModLoader.get().loadMods(Runnable::run, (a)->{}, (a)->{});
try {
ModLoader.get().gatherAndInitializeMods(null);
ModLoader.get().loadMods(Runnable::run, (a)->{}, (a)->{});
} catch (LoadingFailedException e) {
ServerModLoader.hasErrors = true;
throw e;
}
}
public static void end() {
ModLoader.get().finishMods(Runnable::run);
try {
ModLoader.get().finishMods(Runnable::run);
} catch (LoadingFailedException e) {
ServerModLoader.hasErrors = true;
throw e;
}
List<ModLoadingWarning> warnings = ModLoader.get().getWarnings();
if (!warnings.isEmpty()) {
LOGGER.warn(LOADING, "Mods loaded with {} warnings", warnings.size());
@ -56,4 +67,8 @@ public class ServerModLoader
MinecraftForge.EVENT_BUS.start();
server.getServerStatusResponse().setForgeData(new FMLStatusPing()); //gathers NetworkRegistry data
}
public static boolean hasErrors() {
return ServerModLoader.hasErrors;
}
}