Combine all hidden mod resource packs into a single sortable pack

Fix mod datapacks sorting under vanilla
This commit is contained in:
tterrag 2019-10-04 17:16:36 -04:00
parent 8482293b40
commit ca980a56bc
7 changed files with 220 additions and 52 deletions

View File

@ -19,15 +19,37 @@
package net.minecraftforge.fml.client;
import static net.minecraftforge.fml.Logging.CORE;
import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.mojang.blaze3d.platform.GlStateManager;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.DownloadingPackFinder;
import net.minecraft.client.resources.ClientResourcePackInfo;
import net.minecraft.client.resources.DownloadingPackFinder;
import net.minecraft.profiler.IProfiler;
import net.minecraft.resources.IFutureReloadListener;
import net.minecraft.resources.IReloadableResourceManager;
import net.minecraft.resources.IResourceManager;
import net.minecraft.resources.ResourcePackInfo;
import net.minecraft.resources.ResourcePackList;
import net.minecraft.resources.data.PackMetadataSection;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.event.ModelRegistryEvent;
@ -46,27 +68,12 @@ import net.minecraftforge.fml.VersionChecker;
import net.minecraftforge.fml.client.gui.LoadingErrorScreen;
import net.minecraftforge.fml.client.registry.RenderingRegistry;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.packs.DelegatableResourcePack;
import net.minecraftforge.fml.packs.DelegatingResourcePack;
import net.minecraftforge.fml.packs.ModFileResourcePack;
import net.minecraftforge.fml.packs.ResourcePackLoader;
import net.minecraftforge.fml.server.LanguageHook;
import net.minecraftforge.forgespi.language.IModInfo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.mojang.blaze3d.platform.GlStateManager;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import static net.minecraftforge.fml.Logging.CORE;
import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
@OnlyIn(Dist.CLIENT)
public class ClientModLoader
@ -173,17 +180,18 @@ public class ClientModLoader
return loading;
}
private static <T extends ResourcePackInfo> ResourcePackLoader.IPackInfoFinder<T> buildPackFinder(Map<ModFile, ModFileResourcePack> modResourcePacks, BiConsumer<ModFileResourcePack, T> packSetter) {
private static <T extends ResourcePackInfo> ResourcePackLoader.IPackInfoFinder<T> buildPackFinder(Map<ModFile, ? extends ModFileResourcePack> modResourcePacks, BiConsumer<? super ModFileResourcePack, ? super T> packSetter) {
return (packList, factory) -> clientPackFinder(modResourcePacks, packSetter, packList, factory);
}
private static <T extends ResourcePackInfo> void clientPackFinder(Map<ModFile, ModFileResourcePack> modResourcePacks, BiConsumer<ModFileResourcePack, T> packSetter, Map<String, T> packList, ResourcePackInfo.IFactory<T> factory) {
for (Map.Entry<ModFile, ModFileResourcePack> e : modResourcePacks.entrySet())
private static <T extends ResourcePackInfo> void clientPackFinder(Map<ModFile, ? extends ModFileResourcePack> modResourcePacks, BiConsumer<? super ModFileResourcePack, ? super T> packSetter, Map<String, T> packList, ResourcePackInfo.IFactory<? extends T> factory) {
List<DelegatableResourcePack> hiddenPacks = new ArrayList<>();
for (Entry<ModFile, ? extends ModFileResourcePack> e : modResourcePacks.entrySet())
{
IModInfo mod = e.getKey().getModInfos().get(0);
if (Objects.equals(mod.getModId(), "minecraft")) continue; // skip the minecraft "mod"
final String name = "mod:" + mod.getModId();
final T packInfo = ResourcePackInfo.createResourcePack(name, true, e::getValue, factory, ResourcePackInfo.Priority.BOTTOM);
final T packInfo = ResourcePackInfo.createResourcePack(name, false, e::getValue, factory, ResourcePackInfo.Priority.BOTTOM);
if (packInfo == null) {
// Vanilla only logs an error, instead of propagating, so handle null and warn that something went wrong
ModLoader.get().addWarning(new ModLoadingWarning(mod, ModLoadingStage.ERROR, "fml.modloading.brokenresources", e.getKey()));
@ -191,7 +199,15 @@ public class ClientModLoader
}
packSetter.accept(e.getValue(), packInfo);
LOGGER.debug(CORE, "Generating PackInfo named {} for mod file {}", name, e.getKey().getFilePath());
packList.put(name, packInfo);
if (mod.getOwningFile().showAsResourcePack()) {
packList.put(name, packInfo);
} else {
hiddenPacks.add(e.getValue());
}
}
final T packInfo = ResourcePackInfo.createResourcePack("mod_resources", true, () -> new DelegatingResourcePack("mod_resources", "Mod Resources",
new PackMetadataSection(new TranslationTextComponent("fml.resources.modresources", hiddenPacks.size()), 4),
hiddenPacks), factory, ResourcePackInfo.Priority.BOTTOM);
packList.put("mod_resources", packInfo);
}
}

View File

@ -0,0 +1,21 @@
package net.minecraftforge.fml.packs;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import net.minecraft.resources.ResourcePack;
public abstract class DelegatableResourcePack extends ResourcePack
{
protected DelegatableResourcePack(File resourcePackFileIn)
{
super(resourcePackFileIn);
}
@Override
public abstract InputStream getInputStream(String resourcePath) throws IOException;
@Override
public abstract boolean resourceExists(String resourcePath);
}

View File

@ -0,0 +1,133 @@
package net.minecraftforge.fml.packs;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import net.minecraft.resources.ResourcePack;
import net.minecraft.resources.ResourcePackFileNotFoundException;
import net.minecraft.resources.ResourcePackType;
import net.minecraft.resources.data.IMetadataSectionSerializer;
import net.minecraft.resources.data.PackMetadataSection;
import net.minecraft.util.ResourceLocation;
public class DelegatingResourcePack extends ResourcePack
{
private final List<DelegatableResourcePack> delegates = new ArrayList<>();
private final String name;
private final PackMetadataSection packInfo;
public DelegatingResourcePack(String id, String name, PackMetadataSection packInfo)
{
this(id, name, packInfo, Collections.emptyList());
}
public DelegatingResourcePack(String id, String name, PackMetadataSection packInfo, List<DelegatableResourcePack> packs)
{
super(new File(id));
this.name = name;
this.packInfo = packInfo;
packs.forEach(this::addDelegate);
}
public void addDelegate(DelegatableResourcePack pack)
{
synchronized(delegates)
{
this.delegates.add(pack);
}
}
@Override
public String getName()
{
return name;
}
@SuppressWarnings("unchecked")
@Override
public <T> T getMetadata(IMetadataSectionSerializer<T> deserializer) throws IOException
{
if (deserializer.getSectionName().equals("pack"))
{
return (T) packInfo;
}
return null;
}
@Override
public Collection<ResourceLocation> getAllResourceLocations(ResourcePackType type, String pathIn, int maxDepth, Predicate<String> filter)
{
synchronized(delegates)
{
return delegates.stream()
.flatMap(r -> r.getAllResourceLocations(type, pathIn, maxDepth, filter).stream())
.collect(Collectors.toList());
}
}
@Override
public Set<String> getResourceNamespaces(ResourcePackType type)
{
synchronized (delegates)
{
return delegates.stream()
.flatMap(r -> r.getResourceNamespaces(type).stream())
.collect(Collectors.toSet());
}
}
@Override
public void close() throws IOException
{
synchronized(delegates)
{
for (ResourcePack pack : delegates)
{
pack.close();
}
}
}
@Override
protected InputStream getInputStream(String resourcePath) throws IOException
{
if (!resourcePath.equals("pack.png")) // Mods shouldn't be able to mess with the pack icon
{
synchronized (delegates)
{
for (DelegatableResourcePack pack : delegates)
{
if (pack.resourceExists(resourcePath))
{
return pack.getInputStream(resourcePath);
}
}
}
}
throw new ResourcePackFileNotFoundException(this.file, resourcePath);
}
@Override
protected boolean resourceExists(String resourcePath)
{
synchronized (delegates)
{
for (DelegatableResourcePack pack : delegates)
{
if (pack.resourceExists(resourcePath))
{
return true;
}
}
}
return false;
}
}

View File

@ -52,7 +52,7 @@ import org.apache.logging.log4j.Logger;
import static net.minecraftforge.fml.Logging.CORE;
public class ModFileResourcePack extends ResourcePack
public class ModFileResourcePack extends DelegatableResourcePack
{
private final ModFile modFile;
private ResourcePackInfo packInfo;
@ -74,14 +74,14 @@ public class ModFileResourcePack extends ResourcePack
}
@Override
protected InputStream getInputStream(String name) throws IOException
public InputStream getInputStream(String name) throws IOException
{
final Path path = modFile.getLocator().findPath(modFile, name);
return Files.newInputStream(path, StandardOpenOption.READ);
}
@Override
protected boolean resourceExists(String name)
public boolean resourceExists(String name)
{
return Files.exists(modFile.getLocator().findPath(modFile, name));
}
@ -146,7 +146,6 @@ public class ModFileResourcePack extends ResourcePack
}
}
@Override
public void close() throws IOException
{
@ -160,9 +159,4 @@ public class ModFileResourcePack extends ResourcePack
<T extends ResourcePackInfo> T getPackInfo() {
return (T)this.packInfo;
}
@Override
public boolean isHidden() {
return !modFile.getModFileInfo().showAsResourcePack();
}
}

View File

@ -32,6 +32,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.minecraft.resources.IPackFinder;
import net.minecraft.resources.ResourcePack;
import net.minecraft.resources.ResourcePackInfo;
import net.minecraft.resources.ResourcePackList;
import net.minecraftforge.fml.ModList;
@ -49,7 +50,7 @@ public class ResourcePackLoader
map(ModFileInfo::getFile).map(mf->modResourcePacks.get(mf));
}
public static <T extends ResourcePackInfo> void loadResourcePacks(ResourcePackList<T> resourcePacks, BiFunction<Map<ModFile, ModFileResourcePack>, BiConsumer<ModFileResourcePack, T>, IPackInfoFinder> packFinder) {
public static <T extends ResourcePackInfo> void loadResourcePacks(ResourcePackList<T> resourcePacks, BiFunction<Map<ModFile, ? extends ModFileResourcePack>, BiConsumer<? super ModFileResourcePack, T>, IPackInfoFinder> packFinder) {
resourcePackList = resourcePacks;
modResourcePacks = ModList.get().getModFiles().stream().
filter(mf->!Objects.equals(mf.getModLoader(),"minecraft")).

View File

@ -19,8 +19,23 @@
package net.minecraftforge.fml.server;
import net.minecraft.network.ProtocolType;
import static net.minecraftforge.fml.Logging.CORE;
import java.nio.file.Path;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.ProtocolType;
import net.minecraft.network.handshake.client.CHandshakePacket;
import net.minecraft.network.login.server.SDisconnectLoginPacket;
import net.minecraft.resources.ResourcePackInfo;
@ -36,8 +51,8 @@ import net.minecraftforge.fml.ModLoadingWarning;
import net.minecraftforge.fml.config.ConfigTracker;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppedEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
import net.minecraftforge.fml.loading.FileUtils;
@ -49,19 +64,6 @@ import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.fml.packs.ModFileResourcePack;
import net.minecraftforge.fml.packs.ResourcePackLoader;
import net.minecraftforge.forgespi.language.IModInfo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import java.nio.file.Path;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import static net.minecraftforge.fml.Logging.CORE;
public class ServerLifecycleHooks
{
@ -193,17 +195,17 @@ public class ServerLifecycleHooks
System.exit(retVal);
}
private static <T extends ResourcePackInfo> ResourcePackLoader.IPackInfoFinder<T> buildPackFinder(Map<ModFile, ModFileResourcePack> modResourcePacks, BiConsumer<ModFileResourcePack, T> packSetter) {
private static <T extends ResourcePackInfo> ResourcePackLoader.IPackInfoFinder<T> buildPackFinder(Map<ModFile, ? extends ModFileResourcePack> modResourcePacks, BiConsumer<? super ModFileResourcePack, ? super T> packSetter) {
return (packList, factory) -> serverPackFinder(modResourcePacks, packSetter, packList, factory);
}
private static <T extends ResourcePackInfo> void serverPackFinder(Map<ModFile, ModFileResourcePack> modResourcePacks, BiConsumer<ModFileResourcePack, T> packSetter, Map<String, T> packList, ResourcePackInfo.IFactory<T> factory) {
for (Map.Entry<ModFile, ModFileResourcePack> e : modResourcePacks.entrySet())
private static <T extends ResourcePackInfo> void serverPackFinder(Map<ModFile, ? extends ModFileResourcePack> modResourcePacks, BiConsumer<? super ModFileResourcePack, ? super T> packSetter, Map<String, T> packList, ResourcePackInfo.IFactory<? extends T> factory) {
for (Entry<ModFile, ? extends ModFileResourcePack> e : modResourcePacks.entrySet())
{
IModInfo mod = e.getKey().getModInfos().get(0);
if (Objects.equals(mod.getModId(), "minecraft")) continue; // skip the minecraft "mod"
final String name = "mod:" + mod.getModId();
final T packInfo = ResourcePackInfo.createResourcePack(name, true, e::getValue, factory, ResourcePackInfo.Priority.BOTTOM);
final T packInfo = ResourcePackInfo.createResourcePack(name, true, e::getValue, factory, ResourcePackInfo.Priority.TOP);
if (packInfo == null) {
// Vanilla only logs an error, instead of propagating, so handle null and warn that something went wrong
ModLoader.get().addWarning(new ModLoadingWarning(mod, ModLoadingStage.ERROR, "fml.modloading.brokenresources", e.getKey()));

View File

@ -57,6 +57,7 @@
"fml.modloading.brokenfile.optifine": "File {2} is an incompatible version of OptiFine",
"fml.modloading.brokenfile.invalidzip": "File {2} is not a jar file",
"fml.modloading.brokenresources": "File {2} failed to load a valid ResourcePackInfo",
"fml.resources.modresources": "Resources for {0} mod files",
"fml.messages.artifactversion.ornotinstalled":"{0,ornull,fml.messages.artifactversion.notinstalled}",
"fml.messages.artifactversion":"{0,ornull,fml.messages.artifactversion.none}",