From d8711097418b73aa75a44ea90f424b8a29393cd5 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Sun, 17 Dec 2023 20:00:52 +0900 Subject: [PATCH 01/23] First step toward fixing resource pack grouping --- .../FabricWrappedVanillaResourcePack.java | 63 -------------- ...efaultClientResourcePackProviderMixin.java | 77 ----------------- ...bric-resource-loader-v0.client.mixins.json | 1 - .../fabric/api/resource/ModResourcePack.java | 2 + .../loader/FabricModResourcePack.java | 86 ------------------- .../resource/loader/ModNioResourcePack.java | 51 ++++++----- .../loader/ModResourcePackCreator.java | 49 +++-------- .../loader/ModResourcePackFactory.java | 48 +++++++++++ .../resource/loader/ModResourcePackUtil.java | 32 +++++-- .../loader/ResourceManagerHelperImpl.java | 4 +- .../loader/ResourcePackSourceTracker.java | 1 - .../loader/NamespaceResourceManagerMixin.java | 63 -------------- .../ReloadableResourceManagerImplMixin.java | 46 ---------- .../mixin/resource/loader/ResourceMixin.java | 2 - .../fabric-resource-loader-v0.mixins.json | 2 - 15 files changed, 119 insertions(+), 408 deletions(-) delete mode 100644 fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/FabricWrappedVanillaResourcePack.java delete mode 100644 fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/DefaultClientResourcePackProviderMixin.java delete mode 100644 fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricModResourcePack.java create mode 100644 fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackFactory.java delete mode 100644 fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/NamespaceResourceManagerMixin.java delete mode 100644 fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ReloadableResourceManagerImplMixin.java diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/FabricWrappedVanillaResourcePack.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/FabricWrappedVanillaResourcePack.java deleted file mode 100644 index 8d21cac073..0000000000 --- a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/FabricWrappedVanillaResourcePack.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.impl.client.resource.loader; - -import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import java.util.stream.Stream; - -import org.jetbrains.annotations.Nullable; - -import net.minecraft.resource.AbstractFileResourcePack; -import net.minecraft.resource.InputSupplier; -import net.minecraft.resource.ResourceType; -import net.minecraft.resource.metadata.ResourceMetadataReader; - -import net.fabricmc.fabric.api.resource.ModResourcePack; -import net.fabricmc.fabric.impl.resource.loader.GroupResourcePack; - -/** - * Represents a vanilla built-in resource pack with support for modded content. - * - *

Vanilla resources are provided as usual through the original resource pack (if not overridden), - * all other resources will be searched for in the provided modded resource packs.

- */ -public class FabricWrappedVanillaResourcePack extends GroupResourcePack { - private final AbstractFileResourcePack originalResourcePack; - - public FabricWrappedVanillaResourcePack(AbstractFileResourcePack originalResourcePack, List modResourcePacks) { - // Mod resource packs have higher priority, add them last (so vanilla assets can be overridden) - super(ResourceType.CLIENT_RESOURCES, Stream.concat(Stream.of(originalResourcePack), modResourcePacks.stream()).toList()); - this.originalResourcePack = originalResourcePack; - } - - @Override - public InputSupplier openRoot(String... pathSegments) { - return this.originalResourcePack.openRoot(pathSegments); - } - - @Override - public @Nullable T parseMetadata(ResourceMetadataReader metaReader) throws IOException { - return this.originalResourcePack.parseMetadata(metaReader); - } - - @Override - public String getName() { - return this.originalResourcePack.getName(); - } -} diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/DefaultClientResourcePackProviderMixin.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/DefaultClientResourcePackProviderMixin.java deleted file mode 100644 index b3d1015e9a..0000000000 --- a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/DefaultClientResourcePackProviderMixin.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.mixin.resource.loader.client; - -import java.util.ArrayList; -import java.util.List; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyArg; - -import net.minecraft.client.resource.DefaultClientResourcePackProvider; -import net.minecraft.resource.AbstractFileResourcePack; -import net.minecraft.resource.ResourcePack; -import net.minecraft.resource.ResourcePackProfile; -import net.minecraft.resource.ResourcePackSource; -import net.minecraft.resource.ResourceType; -import net.minecraft.text.Text; - -import net.fabricmc.fabric.api.resource.ModResourcePack; -import net.fabricmc.fabric.impl.client.resource.loader.FabricWrappedVanillaResourcePack; -import net.fabricmc.fabric.impl.resource.loader.ModResourcePackUtil; - -@Mixin(DefaultClientResourcePackProvider.class) -public class DefaultClientResourcePackProviderMixin { - /** - * Injects into the method which registers/creates vanilla built-in resource packs, - * and replaces the local {@link net.minecraft.resource.ResourcePackProfile.PackFactory} - * instance with our custom wrapper that supports loading from mods. - */ - @ModifyArg( - method = "create(Ljava/lang/String;Lnet/minecraft/resource/ResourcePackProfile$PackFactory;Lnet/minecraft/text/Text;)Lnet/minecraft/resource/ResourcePackProfile;", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/resource/ResourcePackProfile;create(Ljava/lang/String;Lnet/minecraft/text/Text;ZLnet/minecraft/resource/ResourcePackProfile$PackFactory;Lnet/minecraft/resource/ResourceType;Lnet/minecraft/resource/ResourcePackProfile$InsertionPosition;Lnet/minecraft/resource/ResourcePackSource;)Lnet/minecraft/resource/ResourcePackProfile;" - ), - index = 3 - ) - private ResourcePackProfile.PackFactory onCreateVanillaBuiltinResourcePack(String name, Text displayName, boolean alwaysEnabled, - ResourcePackProfile.PackFactory packFactory, ResourceType type, ResourcePackProfile.InsertionPosition position, ResourcePackSource source) { - return new ResourcePackProfile.PackFactory() { - @Override - public ResourcePack open(String name) { - return new FabricWrappedVanillaResourcePack((AbstractFileResourcePack) packFactory.open(name), getModResourcePacks(name)); - } - - @Override - public ResourcePack openWithOverlays(String string, ResourcePackProfile.Metadata metadata) { - // VanillaResourcePackProvider does not handle overlays - return open(name); - } - }; - } - - /** - * {@return all baked-in mod resource packs that provide resources in the specified subPath}. - */ - private static List getModResourcePacks(String subPath) { - List packs = new ArrayList<>(); - ModResourcePackUtil.appendModResourcePacks(packs, ResourceType.CLIENT_RESOURCES, subPath); - return packs; - } -} diff --git a/fabric-resource-loader-v0/src/client/resources/fabric-resource-loader-v0.client.mixins.json b/fabric-resource-loader-v0/src/client/resources/fabric-resource-loader-v0.client.mixins.json index 8230da5131..9920bc5d27 100644 --- a/fabric-resource-loader-v0/src/client/resources/fabric-resource-loader-v0.client.mixins.json +++ b/fabric-resource-loader-v0/src/client/resources/fabric-resource-loader-v0.client.mixins.json @@ -4,7 +4,6 @@ "compatibilityLevel": "JAVA_17", "client": [ "VanillaResourcePackProviderMixin", - "DefaultClientResourcePackProviderMixin", "CreateWorldScreenMixin", "FontManagerMixin", "GameOptionsMixin", diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/api/resource/ModResourcePack.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/api/resource/ModResourcePack.java index e66b3606df..b707e742fe 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/api/resource/ModResourcePack.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/api/resource/ModResourcePack.java @@ -29,4 +29,6 @@ public interface ModResourcePack extends ResourcePack { * resource pack. */ ModMetadata getFabricModMetadata(); + + ModResourcePack createOverlay(String overlay); } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricModResourcePack.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricModResourcePack.java deleted file mode 100644 index 1296eaaf41..0000000000 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricModResourcePack.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.impl.resource.loader; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.util.List; - -import com.google.common.base.Charsets; -import org.apache.commons.io.IOUtils; -import org.jetbrains.annotations.Nullable; - -import net.minecraft.SharedConstants; -import net.minecraft.resource.AbstractFileResourcePack; -import net.minecraft.resource.InputSupplier; -import net.minecraft.resource.ResourceType; -import net.minecraft.resource.metadata.ResourceMetadataReader; - -import net.fabricmc.fabric.api.resource.ModResourcePack; -import net.fabricmc.loader.api.FabricLoader; - -/** - * The Fabric mods resource pack, holds all the mod resource packs as one pack. - */ -public class FabricModResourcePack extends GroupResourcePack { - public FabricModResourcePack(ResourceType type, List packs) { - super(type, packs); - } - - @Override - public InputSupplier openRoot(String... pathSegments) { - String fileName = String.join("/", pathSegments); - - if ("pack.mcmeta".equals(fileName)) { - String description = "pack.description.modResources"; - String fallback = "Mod resources."; - String pack = String.format("{\"pack\":{\"pack_format\":" + SharedConstants.getGameVersion().getResourceVersion(type) + ",\"description\":{\"translate\":\"%s\",\"fallback\":\"%s.\"}}}", description, fallback); - return () -> IOUtils.toInputStream(pack, Charsets.UTF_8); - } else if ("pack.png".equals(fileName)) { - return FabricLoader.getInstance().getModContainer("fabric-resource-loader-v0") - .flatMap(container -> container.getMetadata().getIconPath(512).flatMap(container::findPath)) - .map(path -> (InputSupplier) (() -> Files.newInputStream(path))) - .orElse(null); - } - - return null; - } - - @Override - public @Nullable T parseMetadata(ResourceMetadataReader metaReader) throws IOException { - InputSupplier inputSupplier = this.openRoot("pack.mcmeta"); - - if (inputSupplier != null) { - try (InputStream input = inputSupplier.get()) { - return AbstractFileResourcePack.parseMetadata(metaReader, input); - } - } else { - return null; - } - } - - @Override - public String getName() { - return "fabric"; - } - - @Override - public boolean isAlwaysStable() { - return true; - } -} diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModNioResourcePack.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModNioResourcePack.java index fa56fe02e2..e1c42d4472 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModNioResourcePack.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModNioResourcePack.java @@ -33,6 +33,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; @@ -59,14 +60,18 @@ public class ModNioResourcePack implements ResourcePack, ModResourcePack { private static final FileSystem DEFAULT_FS = FileSystems.getDefault(); private final String id; - private final ModMetadata modInfo; + private final ModContainer mod; private final List basePaths; private final ResourceType type; - private final AutoCloseable closer; private final ResourcePackActivationType activationType; private final Map> namespaces; + /** + * Whether the pack is bundled and loaded by default, as opposed to registered built-in packs. + * @see ModResourcePackUtil#appendModResourcePacks(List, ResourceType, String) + */ + private final boolean modBundled; - public static ModNioResourcePack create(String id, ModContainer mod, String subPath, ResourceType type, ResourcePackActivationType activationType) { + public static ModNioResourcePack create(String id, ModContainer mod, String subPath, ResourceType type, ResourcePackActivationType activationType, boolean modBundled) { List rootPaths = mod.getRootPaths(); List paths; @@ -89,19 +94,27 @@ public static ModNioResourcePack create(String id, ModContainer mod, String subP if (paths.isEmpty()) return null; - ModNioResourcePack ret = new ModNioResourcePack(id, mod.getMetadata(), paths, type, null, activationType); + ModNioResourcePack ret = new ModNioResourcePack(id, mod, paths, type, activationType, modBundled); return ret.getNamespaces(type).isEmpty() ? null : ret; } - private ModNioResourcePack(String id, ModMetadata modInfo, List paths, ResourceType type, AutoCloseable closer, ResourcePackActivationType activationType) { + private ModNioResourcePack(String id, ModContainer mod, List paths, ResourceType type, ResourcePackActivationType activationType, boolean modBundled) { this.id = id; - this.modInfo = modInfo; + this.mod = mod; this.basePaths = paths; this.type = type; - this.closer = closer; this.activationType = activationType; - this.namespaces = readNamespaces(paths, modInfo.getId()); + this.modBundled = modBundled; + this.namespaces = readNamespaces(paths, mod.getMetadata().getId()); + } + + @Override + public ModNioResourcePack createOverlay(String overlay) { + // See DirectoryResourcePack. + return new ModNioResourcePack(id, mod, basePaths.stream().map( + path -> path.resolve(overlay) + ).toList(), type, activationType, modBundled); } static Map> readNamespaces(List paths, String modId) { @@ -188,8 +201,8 @@ private InputSupplier openFile(String filename) { return () -> Files.newInputStream(path); } - if (ModResourcePackUtil.containsDefault(this.modInfo, filename)) { - return () -> ModResourcePackUtil.openDefault(this.modInfo, this.type, filename); + if (ModResourcePackUtil.containsDefault(filename, this.modBundled)) { + return () -> ModResourcePackUtil.openDefault(this.mod, this.type, filename); } return null; @@ -239,7 +252,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { } }); } catch (IOException e) { - LOGGER.warn("findResources at " + path + " in namespace " + namespace + ", mod " + modInfo.getId() + " failed!", e); + LOGGER.warn("findResources at " + path + " in namespace " + namespace + ", mod " + mod.getMetadata().getId() + " failed!", e); } } } @@ -251,25 +264,18 @@ public Set getNamespaces(ResourceType type) { @Override public T parseMetadata(ResourceMetadataReader metaReader) throws IOException { - try (InputStream is = openFile("pack.mcmeta").get()) { + try (InputStream is = Objects.requireNonNull(openFile("pack.mcmeta")).get()) { return AbstractFileResourcePack.parseMetadata(metaReader, is); } } @Override public void close() { - if (closer != null) { - try { - closer.close(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } } @Override public ModMetadata getFabricModMetadata() { - return modInfo; + return mod.getMetadata(); } public ResourcePackActivationType getActivationType() { @@ -281,6 +287,11 @@ public String getName() { return id; } + @Override + public boolean isAlwaysStable() { + return this.modBundled; + } + private static boolean exists(Path path) { // NIO Files.exists is notoriously slow when checking the file system return path.getFileSystem() == DEFAULT_FS ? path.toFile().exists() : Files.exists(path); diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java index 484c2deab0..2fb5e991e3 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java @@ -20,13 +20,10 @@ import java.util.List; import java.util.function.Consumer; -import net.minecraft.resource.OverlayResourcePack; -import net.minecraft.resource.ResourcePack; import net.minecraft.resource.ResourcePackProfile; import net.minecraft.resource.ResourcePackProvider; import net.minecraft.resource.ResourcePackSource; import net.minecraft.resource.ResourceType; -import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.fabricmc.fabric.api.resource.ModResourcePack; @@ -76,42 +73,16 @@ public void register(Consumer consumer) { List packs = new ArrayList<>(); ModResourcePackUtil.appendModResourcePacks(packs, type, null); - if (!packs.isEmpty()) { - // Make the resource pack profile for mod resource packs. - // Mod resource packs must always be enabled to avoid issues, and they are inserted - // on top to ensure that they are applied after vanilla built-in resource packs. - MutableText title = Text.translatable("pack.name.fabricMods"); - ResourcePackProfile resourcePackProfile = ResourcePackProfile.create("fabric", title, true, new ResourcePackProfile.PackFactory() { - @Override - public ResourcePack open(String name) { - return new FabricModResourcePack(type, packs); - } - - @Override - public ResourcePack openWithOverlays(String name, ResourcePackProfile.Metadata metadata) { - final ResourcePack basePack = open(name); - final List overlays = metadata.overlays(); - - if (overlays.isEmpty()) { - return basePack; - } - - final List overlayedPacks = new ArrayList<>(overlays.size()); - - for (String overlay : overlays) { - List innerPacks = new ArrayList<>(); - ModResourcePackUtil.appendModResourcePacks(innerPacks, type, overlay); - - overlayedPacks.add(new FabricModResourcePack(type, innerPacks)); - } - - return new OverlayResourcePack(basePack, overlayedPacks); - } - }, type, ResourcePackProfile.InsertionPosition.TOP, RESOURCE_PACK_SOURCE); - - if (resourcePackProfile != null) { - consumer.accept(resourcePackProfile); - } + for (ModResourcePack pack : packs) { + consumer.accept(ResourcePackProfile.create( + pack.getName(), + Text.translatable("pack.name.fabricMod", pack.getFabricModMetadata().getName()), + true, + new ModResourcePackFactory(pack), + type, + ResourcePackProfile.InsertionPosition.TOP, + RESOURCE_PACK_SOURCE + )); } // Register all built-in resource packs provided by mods. diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackFactory.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackFactory.java new file mode 100644 index 0000000000..8282470ce5 --- /dev/null +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackFactory.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.resource.loader; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.resource.OverlayResourcePack; +import net.minecraft.resource.ResourcePack; +import net.minecraft.resource.ResourcePackProfile; + +import net.fabricmc.fabric.api.resource.ModResourcePack; + +public record ModResourcePackFactory(ModResourcePack pack) implements ResourcePackProfile.PackFactory { + @Override + public ResourcePack open(String name) { + return pack; + } + + @Override + public ResourcePack openWithOverlays(String name, ResourcePackProfile.Metadata metadata) { + if (metadata.overlays().isEmpty()) { + return pack; + } else { + List overlays = new ArrayList<>(metadata.overlays().size()); + + for (String overlay : metadata.overlays()) { + overlays.add(pack.createOverlay(overlay)); + } + + return new OverlayResourcePack(pack, overlays); + } + } +} diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java index 1038e88dee..6de0b7aa60 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java @@ -16,12 +16,16 @@ package net.fabricmc.fabric.impl.resource.loader; +import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.Set; import com.google.common.base.Charsets; @@ -67,7 +71,7 @@ public static void appendModResourcePacks(List packs, ResourceT continue; } - ModResourcePack pack = ModNioResourcePack.create(container.getMetadata().getId(), container, subPath, type, ResourcePackActivationType.ALWAYS_ENABLED); + ModResourcePack pack = ModNioResourcePack.create(container.getMetadata().getId(), container, subPath, type, ResourcePackActivationType.ALWAYS_ENABLED, true); if (pack != null) { packs.add(pack); @@ -75,16 +79,32 @@ public static void appendModResourcePacks(List packs, ResourceT } } - public static boolean containsDefault(ModMetadata info, String filename) { - return "pack.mcmeta".equals(filename); + public static boolean containsDefault(String filename, boolean modBundled) { + return "pack.mcmeta".equals(filename) || (modBundled && "pack.png".equals(filename)); } - public static InputStream openDefault(ModMetadata info, ResourceType type, String filename) { + public static InputStream openDefault(ModContainer container, ResourceType type, String filename) throws IOException { switch (filename) { case "pack.mcmeta": - String description = Objects.requireNonNullElse(info.getName(), ""); + String description = Objects.requireNonNullElse(container.getMetadata().getName(), ""); String metadata = serializeMetadata(SharedConstants.getGameVersion().getResourceVersion(type), description); return IOUtils.toInputStream(metadata, Charsets.UTF_8); + case "pack.png": + Optional path = container.getMetadata().getIconPath(512).flatMap(container::findPath); + + if (path.isPresent()) { + return Files.newInputStream(path.get()); + } else { + Optional loaderIconPath = FabricLoader.getInstance().getModContainer("fabric-resource-loader-v0") + .flatMap(resourceLoaderContainer -> resourceLoaderContainer.getMetadata().getIconPath(512).flatMap(resourceLoaderContainer::findPath)); + + if (loaderIconPath.isPresent()) { + return Files.newInputStream(loaderIconPath.get()); + } + + // Should never happen in practice + return null; + } default: return null; } @@ -124,7 +144,7 @@ public static DataConfiguration createDefaultDataConfiguration() { // as the data pack screen automatically put any data pack as disabled except the Default data pack. for (ResourcePackProfile profile : moddedResourcePacks) { try (ResourcePack pack = profile.createResourcePack()) { - if (pack instanceof FabricModResourcePack || (pack instanceof ModNioResourcePack && ((ModNioResourcePack) pack).getActivationType().isEnabledByDefault())) { + if (pack instanceof ModNioResourcePack && ((ModNioResourcePack) pack).getActivationType().isEnabledByDefault()) { enabled.add(profile.getName()); } else { disabled.add(profile.getName()); diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ResourceManagerHelperImpl.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ResourceManagerHelperImpl.java index e7b25f74a2..d45c6d8ce9 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ResourceManagerHelperImpl.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ResourceManagerHelperImpl.java @@ -74,8 +74,8 @@ public static boolean registerBuiltinResourcePack(Identifier id, String subPath, List paths = container.getRootPaths(); String separator = paths.get(0).getFileSystem().getSeparator(); subPath = subPath.replace("/", separator); - ModNioResourcePack resourcePack = ModNioResourcePack.create(id.toString(), container, subPath, ResourceType.CLIENT_RESOURCES, activationType); - ModNioResourcePack dataPack = ModNioResourcePack.create(id.toString(), container, subPath, ResourceType.SERVER_DATA, activationType); + ModNioResourcePack resourcePack = ModNioResourcePack.create(id.toString(), container, subPath, ResourceType.CLIENT_RESOURCES, activationType, false); + ModNioResourcePack dataPack = ModNioResourcePack.create(id.toString(), container, subPath, ResourceType.SERVER_DATA, activationType, false); if (resourcePack == null && dataPack == null) return false; if (resourcePack != null) { diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ResourcePackSourceTracker.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ResourcePackSourceTracker.java index aecdd4945c..6374b91207 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ResourcePackSourceTracker.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ResourcePackSourceTracker.java @@ -28,7 +28,6 @@ * See {@link net.fabricmc.fabric.mixin.resource.loader.ResourcePackProfileMixin ResourcePackProfileMixin}. * *

The sources are later read for use in {@link FabricResource} and {@link FabricResourceImpl}. - * See {@link net.fabricmc.fabric.mixin.resource.loader.NamespaceResourceManagerMixin NamespaceResourceManagerMixin}. */ public final class ResourcePackSourceTracker { // Use a weak hash map so that if resource packs would be deleted, this won't keep them alive. diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/NamespaceResourceManagerMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/NamespaceResourceManagerMixin.java deleted file mode 100644 index 74f3972a59..0000000000 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/NamespaceResourceManagerMixin.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.mixin.resource.loader; - -import java.io.InputStream; -import java.util.List; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import net.minecraft.resource.InputSupplier; -import net.minecraft.resource.NamespaceResourceManager; -import net.minecraft.resource.Resource; -import net.minecraft.resource.ResourcePack; -import net.minecraft.resource.ResourceType; -import net.minecraft.util.Identifier; - -import net.fabricmc.fabric.impl.resource.loader.GroupResourcePack; - -/** - * Patches getAllResources and method_41265 to work with GroupResourcePack. - */ -@Mixin(NamespaceResourceManager.class) -public class NamespaceResourceManagerMixin { - private final ThreadLocal> fabric$getAllResources$resources = new ThreadLocal<>(); - - @Inject(method = "getAllResources", - at = @At(value = "INVOKE", target = "Ljava/util/List;size()I"), - locals = LocalCapture.CAPTURE_FAILHARD) - private void onGetAllResources(Identifier id, CallbackInfoReturnable> cir, Identifier metadataId, List resources) { - this.fabric$getAllResources$resources.set(resources); - } - - @Redirect(method = "getAllResources", - at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourcePack;open(Lnet/minecraft/resource/ResourceType;Lnet/minecraft/util/Identifier;)Lnet/minecraft/resource/InputSupplier;")) - private InputSupplier onResourceAdd(ResourcePack pack, ResourceType type, Identifier id) { - if (pack instanceof GroupResourcePack) { - ((GroupResourcePack) pack).appendResources(type, id, this.fabric$getAllResources$resources.get()); - - return null; - } - - return pack.open(type, id); - } -} diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ReloadableResourceManagerImplMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ReloadableResourceManagerImplMixin.java deleted file mode 100644 index 80ae55c5a5..0000000000 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ReloadableResourceManagerImplMixin.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.mixin.resource.loader; - -import java.util.List; -import java.util.stream.Collectors; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import net.minecraft.resource.ReloadableResourceManagerImpl; -import net.minecraft.resource.ResourcePack; - -import net.fabricmc.fabric.impl.resource.loader.GroupResourcePack; - -@Mixin(ReloadableResourceManagerImpl.class) -public class ReloadableResourceManagerImplMixin { - // private static synthetic method_29491(Ljava/util/List;)Ljava/lang/Object; - // Supplier lambda in beginMonitoredReload method. - @Inject(method = "method_29491", at = @At("HEAD"), cancellable = true) - private static void getResourcePackNames(List packs, CallbackInfoReturnable cir) { - cir.setReturnValue(packs.stream().map(pack -> { - if (pack instanceof GroupResourcePack) { - return ((GroupResourcePack) pack).getFullName(); - } else { - return pack.getName(); - } - }).collect(Collectors.joining(", "))); - } -} diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourceMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourceMixin.java index bd510500c2..3e89f84642 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourceMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourceMixin.java @@ -27,8 +27,6 @@ /** * Implements {@link FabricResource} (resource source getter/setter) * for vanilla's basic {@link Resource} used for most game resources. - * - * @see NamespaceResourceManagerMixin the usage site for this mixin */ @Mixin(Resource.class) class ResourceMixin implements FabricResource { diff --git a/fabric-resource-loader-v0/src/main/resources/fabric-resource-loader-v0.mixins.json b/fabric-resource-loader-v0/src/main/resources/fabric-resource-loader-v0.mixins.json index a33a2ec0c0..4d85f95810 100644 --- a/fabric-resource-loader-v0/src/main/resources/fabric-resource-loader-v0.mixins.json +++ b/fabric-resource-loader-v0/src/main/resources/fabric-resource-loader-v0.mixins.json @@ -6,8 +6,6 @@ "KeyedResourceReloadListenerMixin", "LifecycledResourceManagerImplMixin", "MinecraftServerMixin", - "NamespaceResourceManagerMixin", - "ReloadableResourceManagerImplMixin", "ResourceMixin", "ResourcePackManagerMixin", "ResourcePackProfileMixin", From dcffe91cc942e137bc7c0c021ddc4e78a594e296 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Mon, 18 Dec 2023 21:52:55 +0900 Subject: [PATCH 02/23] Placeholder pack and pack dependency --- .../loader/FabricResourcePackProfile.java | 45 +++++++ .../loader/ModResourcePackCreator.java | 57 +++++++-- .../resource/loader/ModResourcePackUtil.java | 36 ++++-- .../loader/PlaceholderResourcePack.java | 115 ++++++++++++++++++ .../loader/ResourcePackManagerMixin.java | 45 +++++++ .../loader/ResourcePackProfileMixin.java | 26 +++- .../fabric-resource-loader-v0/lang/en_us.json | 3 +- .../src/main/resources/fabric.mod.json | 5 +- 8 files changed, 307 insertions(+), 25 deletions(-) create mode 100644 fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java create mode 100644 fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java new file mode 100644 index 0000000000..528c5527fb --- /dev/null +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.resource.loader; + +import java.util.Collections; +import java.util.Set; +import java.util.function.Predicate; + + +/** + * Interface injected to ResourcePackProfile. + */ +public interface FabricResourcePackProfile { + default boolean isHidden() { + return false; + } + + /** + * @return whether every parent is enabled. + * + *

If this is not empty, the pack's status is synced + * to that of the parent pack(s), where the pack gets enabled if and only if each + * of the parent is enabled. + */ + default boolean parentsEnabled(Set enabled) { + return true; + } + + default void setParentsPredicate(Predicate> predicate) { + } +} diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java index 2fb5e991e3..5bb41fe16b 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java @@ -18,7 +18,11 @@ import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.function.Consumer; +import java.util.function.Predicate; + +import org.jetbrains.annotations.Nullable; import net.minecraft.resource.ResourcePackProfile; import net.minecraft.resource.ResourcePackProvider; @@ -32,6 +36,13 @@ * Represents a resource pack provider for mods and built-in mods resource packs. */ public class ModResourcePackCreator implements ResourcePackProvider { + public static final String FABRIC = "fabric"; + private static final String PROGRAMMER_ART = "programmer_art"; + private static final String HIGH_CONTRAST = "high_contrast"; + public static final Set POST_CHANGE_HANDLE_REQUIRED = Set.of(FABRIC, PROGRAMMER_ART, HIGH_CONTRAST); + private static final Predicate> BASE_PARENT = enabled -> enabled.contains(FABRIC); + private static final Predicate> PROGRAMMER_ART_PARENT = enabled -> enabled.contains(FABRIC) && enabled.contains(PROGRAMMER_ART); + private static final Predicate> HIGH_CONTRAST_PARENT = enabled -> enabled.contains(FABRIC) && enabled.contains(HIGH_CONTRAST); public static final ResourcePackSource RESOURCE_PACK_SOURCE = new ResourcePackSource() { @Override public Text decorate(Text packName) { @@ -69,23 +80,51 @@ public void register(Consumer consumer) { 4. User resource packs */ + consumer.accept(ResourcePackProfile.create( + FABRIC, + Text.translatable("pack.name.fabricMods"), + true, + new PlaceholderResourcePack.Factory(this.type), + this.type, + ResourcePackProfile.InsertionPosition.TOP, + RESOURCE_PACK_SOURCE + )); + // Build a list of mod resource packs. + registerModPack(consumer, null, BASE_PARENT); + + if (this.type == ResourceType.CLIENT_RESOURCES) { + // Programmer Art/High Contrast data packs can never be enabled. + registerModPack(consumer, PROGRAMMER_ART, PROGRAMMER_ART_PARENT); + registerModPack(consumer, HIGH_CONTRAST, HIGH_CONTRAST_PARENT); + } + + // Register all built-in resource packs provided by mods. + ResourceManagerHelperImpl.registerBuiltinResourcePacks(this.type, consumer); + } + + private void registerModPack(Consumer consumer, @Nullable String subPath, Predicate> parents) { List packs = new ArrayList<>(); - ModResourcePackUtil.appendModResourcePacks(packs, type, null); + ModResourcePackUtil.appendModResourcePacks(packs, this.type, subPath); for (ModResourcePack pack : packs) { - consumer.accept(ResourcePackProfile.create( + Text displayName = subPath == null + ? Text.translatable("pack.name.fabricMod", pack.getFabricModMetadata().getName()) + : Text.translatable("pack.name.fabricMod.subPack", pack.getFabricModMetadata().getName(), Text.translatable("resourcePack." + subPath + ".name")); + ResourcePackProfile profile = ResourcePackProfile.create( pack.getName(), - Text.translatable("pack.name.fabricMod", pack.getFabricModMetadata().getName()), - true, + displayName, + subPath == null, new ModResourcePackFactory(pack), - type, + this.type, ResourcePackProfile.InsertionPosition.TOP, RESOURCE_PACK_SOURCE - )); - } + ); - // Register all built-in resource packs provided by mods. - ResourceManagerHelperImpl.registerBuiltinResourcePacks(this.type, consumer); + if (profile != null) { + profile.setParentsPredicate(parents); + consumer.accept(profile); + } + } } } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java index 6de0b7aa60..29607d70b6 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java @@ -30,7 +30,9 @@ import com.google.common.base.Charsets; import com.google.gson.Gson; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; import org.apache.commons.io.IOUtils; import org.jetbrains.annotations.Nullable; @@ -53,7 +55,7 @@ * Internal utilities for managing resource packs. */ public final class ModResourcePackUtil { - private static final Gson GSON = new Gson(); + public static final Gson GSON = new Gson(); private ModResourcePackUtil() { } @@ -83,6 +85,18 @@ public static boolean containsDefault(String filename, boolean modBundled) { return "pack.mcmeta".equals(filename) || (modBundled && "pack.png".equals(filename)); } + public static InputStream getDefaultIcon() throws IOException { + Optional loaderIconPath = FabricLoader.getInstance().getModContainer("fabric-resource-loader-v0") + .flatMap(resourceLoaderContainer -> resourceLoaderContainer.getMetadata().getIconPath(512).flatMap(resourceLoaderContainer::findPath)); + + if (loaderIconPath.isPresent()) { + return Files.newInputStream(loaderIconPath.get()); + } + + // Should never happen in practice + return null; + } + public static InputStream openDefault(ModContainer container, ResourceType type, String filename) throws IOException { switch (filename) { case "pack.mcmeta": @@ -95,28 +109,24 @@ public static InputStream openDefault(ModContainer container, ResourceType type, if (path.isPresent()) { return Files.newInputStream(path.get()); } else { - Optional loaderIconPath = FabricLoader.getInstance().getModContainer("fabric-resource-loader-v0") - .flatMap(resourceLoaderContainer -> resourceLoaderContainer.getMetadata().getIconPath(512).flatMap(resourceLoaderContainer::findPath)); - - if (loaderIconPath.isPresent()) { - return Files.newInputStream(loaderIconPath.get()); - } - - // Should never happen in practice - return null; + return getDefaultIcon(); } default: return null; } } - public static String serializeMetadata(int packVersion, String description) { + public static JsonObject getMetadataJson(int packVersion, JsonElement description) { JsonObject pack = new JsonObject(); pack.addProperty("pack_format", packVersion); - pack.addProperty("description", description); + pack.add("description", description); JsonObject metadata = new JsonObject(); metadata.add("pack", pack); - return GSON.toJson(metadata); + return metadata; + } + + public static String serializeMetadata(int packVersion, String description) { + return GSON.toJson(getMetadataJson(packVersion, new JsonPrimitive(description))); } public static Text getName(ModMetadata info) { diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java new file mode 100644 index 0000000000..3938fee64f --- /dev/null +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.resource.loader; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Set; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.serialization.JsonOps; +import org.apache.commons.io.IOUtils; +import org.jetbrains.annotations.Nullable; + +import net.minecraft.SharedConstants; +import net.minecraft.resource.InputSupplier; +import net.minecraft.resource.ResourcePack; +import net.minecraft.resource.ResourcePackProfile; +import net.minecraft.resource.ResourceType; +import net.minecraft.resource.metadata.ResourceMetadataReader; +import net.minecraft.text.Text; +import net.minecraft.text.TextCodecs; +import net.minecraft.util.Identifier; + +public record PlaceholderResourcePack(ResourceType type) implements ResourcePack { + public static final Text DESCRIPTION_TEXT = Text.translatable("pack.description.modResources"); + public static final JsonElement DESCRIPTION_JSON = TextCodecs.CODEC.encodeStart(JsonOps.INSTANCE, DESCRIPTION_TEXT).result().get(); + + public JsonObject getMetadata() { + return ModResourcePackUtil.getMetadataJson( + SharedConstants.getGameVersion().getResourceVersion(type), + DESCRIPTION_JSON + ); + } + + @Nullable + @Override + public InputSupplier openRoot(String... segments) { + if (segments.length > 0) { + switch (segments[0]) { + case "pack.mcmeta": + return () -> { + String metadata = ModResourcePackUtil.GSON.toJson(getMetadata()); + return IOUtils.toInputStream(metadata, StandardCharsets.UTF_8); + }; + case "pack.png": + return ModResourcePackUtil::getDefaultIcon; + } + } + + return null; + } + + /** + * This pack has no actual contents. + */ + @Nullable + @Override + public InputSupplier open(ResourceType type, Identifier id) { + return null; + } + + @Override + public void findResources(ResourceType type, String namespace, String prefix, ResultConsumer consumer) { + } + + @Override + public Set getNamespaces(ResourceType type) { + return Collections.emptySet(); + } + + @Nullable + @Override + public T parseMetadata(ResourceMetadataReader metaReader) throws IOException { + return metaReader.fromJson(getMetadata()); + } + + @Override + public String getName() { + return ModResourcePackCreator.FABRIC; + } + + @Override + public void close() { + } + + public record Factory(ResourceType type) implements ResourcePackProfile.PackFactory { + + @Override + public ResourcePack open(String name) { + return new PlaceholderResourcePack(this.type); + } + + @Override + public ResourcePack openWithOverlays(String name, ResourcePackProfile.Metadata metadata) { + return open(name); + } + } +} diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java index f6a0bd59e3..a094bcaf1a 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java @@ -16,9 +16,15 @@ package net.fabricmc.fabric.mixin.resource.loader; +import java.util.Collection; import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; +import com.google.common.base.Functions; +import com.llamalad7.mixinextras.sugar.Local; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; @@ -26,6 +32,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.minecraft.resource.FileResourcePackProvider; import net.minecraft.resource.ResourcePackManager; @@ -43,6 +50,9 @@ public abstract class ResourcePackManagerMixin { @Mutable private Set providers; + @Shadow + private Map profiles; + @Inject(method = "", at = @At("RETURN")) public void construct(ResourcePackProvider[] resourcePackProviders, CallbackInfo info) { // Use a LinkedHashSet to preserve ordering @@ -65,4 +75,39 @@ public void construct(ResourcePackProvider[] resourcePackProviders, CallbackInfo providers.add(new ModResourcePackCreator(ResourceType.SERVER_DATA)); } } + + @Inject(method = "buildEnabledProfiles", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/ImmutableList;copyOf(Ljava/util/Collection;)Lcom/google/common/collect/ImmutableList;", shift = At.Shift.BEFORE)) + private void handleAutoEnableDisable(Collection enabledNames, CallbackInfoReturnable> cir, @Local List enabledAfterFirstRun) { + Set currentlyEnabled = enabledAfterFirstRun.stream().map(ResourcePackProfile::getName).collect(Collectors.toSet()); + enabledAfterFirstRun.removeIf(resourcePackProfile -> !resourcePackProfile.parentsEnabled(currentlyEnabled)); + + for (ResourcePackProfile profile : this.profiles.values()) { + if (profile.parentsEnabled(currentlyEnabled) && !enabledAfterFirstRun.contains(profile)) { + profile.getInitialPosition().insert(enabledAfterFirstRun, profile, Functions.identity(), false); + } + } + } + + @Inject(method = "enable", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z")) + private void handleAutoEnable(String profile, CallbackInfoReturnable cir, @Local List newlyEnabled) { + if (ModResourcePackCreator.POST_CHANGE_HANDLE_REQUIRED.contains(profile)) { + Set currentlyEnabled = newlyEnabled.stream().map(ResourcePackProfile::getName).collect(Collectors.toSet()); + + for (ResourcePackProfile p : this.profiles.values()) { + if (p.parentsEnabled(currentlyEnabled) && !newlyEnabled.contains(p)) { + newlyEnabled.add(p); + } + } + } + } + + + + @Inject(method = "disable", at = @At(value = "INVOKE", target = "Ljava/util/List;remove(Ljava/lang/Object;)Z")) + private void handleAutoDisable(String profile, CallbackInfoReturnable cir, @Local List enabled) { + if (ModResourcePackCreator.POST_CHANGE_HANDLE_REQUIRED.contains(profile)) { + Set currentlyEnabled = enabled.stream().map(ResourcePackProfile::getName).collect(Collectors.toSet()); + enabled.removeIf(p -> !p.parentsEnabled(currentlyEnabled)); + } + } } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackProfileMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackProfileMixin.java index 05f8c413a9..b59524aaa9 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackProfileMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackProfileMixin.java @@ -16,9 +16,14 @@ package net.fabricmc.fabric.mixin.resource.loader; +import java.util.Collections; +import java.util.Set; +import java.util.function.Predicate; + import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -27,6 +32,7 @@ import net.minecraft.resource.ResourcePackProfile; import net.minecraft.resource.ResourcePackSource; +import net.fabricmc.fabric.impl.resource.loader.FabricResourcePackProfile; import net.fabricmc.fabric.impl.resource.loader.ResourcePackSourceTracker; /** @@ -37,13 +43,31 @@ * @see ResourcePackSourceTracker */ @Mixin(ResourcePackProfile.class) -abstract class ResourcePackProfileMixin { +abstract class ResourcePackProfileMixin implements FabricResourcePackProfile { + @Unique + private static final Predicate> DEFAULT_PARENT_PREDICATE = parents -> true; @Shadow @Final private ResourcePackSource source; + @Unique + private Predicate> parentsPredicate = DEFAULT_PARENT_PREDICATE; @Inject(method = "createResourcePack", at = @At("RETURN")) private void onCreateResourcePack(CallbackInfoReturnable info) { ResourcePackSourceTracker.setSource(info.getReturnValue(), source); } + @Override + public boolean isHidden() { + return parentsPredicate != DEFAULT_PARENT_PREDICATE; + } + + @Override + public boolean parentsEnabled(Set enabled) { + return parentsPredicate.test(enabled); + } + + @Override + public void setParentsPredicate(Predicate> predicate) { + this.parentsPredicate = predicate; + } } diff --git a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/en_us.json b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/en_us.json index 3611a8ce40..50b4a32327 100644 --- a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/en_us.json +++ b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/en_us.json @@ -3,5 +3,6 @@ "pack.source.fabricmod": "Fabric mod", "pack.source.builtinMod": "built-in: %s", "pack.name.fabricMod": "Fabric Mod \"%s\"", - "pack.name.fabricMods": "Fabric Mods" + "pack.name.fabricMods": "Fabric Mods", + "pack.name.fabricMod.subPack": "Fabric Mod \"%s\" (%s)" } diff --git a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json index b2987ac3c1..3137226e78 100644 --- a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json +++ b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json @@ -28,6 +28,9 @@ ], "accessWidener": "fabric-resource-loader-v0.accesswidener", "custom": { - "fabric-api:module-lifecycle": "stable" + "fabric-api:module-lifecycle": "stable", + "loom:injected_interfaces": { + "net/minecraft/class_3288": ["net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile"] + } } } From aa5e0a419b944e5ff3bdb07b78161f540dde73e2 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Fri, 22 Dec 2023 00:39:05 +0900 Subject: [PATCH 03/23] Various fixes --- .../loader/FabricResourcePackProfile.java | 10 +++---- .../resource/loader/ModResourcePackUtil.java | 11 ++++---- .../loader/PlaceholderResourcePack.java | 27 ++++++++++--------- .../loader/ResourcePackManagerMixin.java | 4 +-- .../loader/ResourcePackProfileMixin.java | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java index 528c5527fb..9d0b1308f7 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java @@ -16,11 +16,9 @@ package net.fabricmc.fabric.impl.resource.loader; -import java.util.Collections; import java.util.Set; import java.util.function.Predicate; - /** * Interface injected to ResourcePackProfile. */ @@ -30,11 +28,11 @@ default boolean isHidden() { } /** - * @return whether every parent is enabled. + * Returns whether every parent is enabled. If this is not empty, the pack's status + * is synced to that of the parent pack(s), where the pack gets enabled if and only + * if each of the parent is enabled. * - *

If this is not empty, the pack's status is synced - * to that of the parent pack(s), where the pack gets enabled if and only if each - * of the parent is enabled. + * @return whether every parent is enabled. */ default boolean parentsEnabled(Set enabled) { return true; diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java index 29607d70b6..b7b8025eb9 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java @@ -116,17 +116,18 @@ public static InputStream openDefault(ModContainer container, ResourceType type, } } - public static JsonObject getMetadataJson(int packVersion, JsonElement description) { + public static JsonObject getMetadataPackJson(int packVersion, JsonElement description) { JsonObject pack = new JsonObject(); pack.addProperty("pack_format", packVersion); pack.add("description", description); - JsonObject metadata = new JsonObject(); - metadata.add("pack", pack); - return metadata; + return pack; } public static String serializeMetadata(int packVersion, String description) { - return GSON.toJson(getMetadataJson(packVersion, new JsonPrimitive(description))); + JsonObject pack = getMetadataPackJson(packVersion, new JsonPrimitive(description)); + JsonObject metadata = new JsonObject(); + metadata.add("pack", pack); + return GSON.toJson(pack); } public static Text getName(ModMetadata info) { diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java index 3938fee64f..98f8c98923 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java @@ -16,7 +16,6 @@ package net.fabricmc.fabric.impl.resource.loader; -import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Collections; @@ -43,7 +42,7 @@ public record PlaceholderResourcePack(ResourceType type) implements ResourcePack public static final JsonElement DESCRIPTION_JSON = TextCodecs.CODEC.encodeStart(JsonOps.INSTANCE, DESCRIPTION_TEXT).result().get(); public JsonObject getMetadata() { - return ModResourcePackUtil.getMetadataJson( + return ModResourcePackUtil.getMetadataPackJson( SharedConstants.getGameVersion().getResourceVersion(type), DESCRIPTION_JSON ); @@ -54,13 +53,13 @@ public JsonObject getMetadata() { public InputSupplier openRoot(String... segments) { if (segments.length > 0) { switch (segments[0]) { - case "pack.mcmeta": - return () -> { - String metadata = ModResourcePackUtil.GSON.toJson(getMetadata()); - return IOUtils.toInputStream(metadata, StandardCharsets.UTF_8); - }; - case "pack.png": - return ModResourcePackUtil::getDefaultIcon; + case "pack.mcmeta": + return () -> { + String metadata = ModResourcePackUtil.GSON.toJson(getMetadata()); + return IOUtils.toInputStream(metadata, StandardCharsets.UTF_8); + }; + case "pack.png": + return ModResourcePackUtil::getDefaultIcon; } } @@ -87,8 +86,13 @@ public Set getNamespaces(ResourceType type) { @Nullable @Override - public T parseMetadata(ResourceMetadataReader metaReader) throws IOException { - return metaReader.fromJson(getMetadata()); + public T parseMetadata(ResourceMetadataReader metaReader) { + if ("pack".equals(metaReader.getKey())) { + return metaReader.fromJson(getMetadata()); + } + + // This pack does not have any overlays. + return null; } @Override @@ -101,7 +105,6 @@ public void close() { } public record Factory(ResourceType type) implements ResourcePackProfile.PackFactory { - @Override public ResourcePack open(String name) { return new PlaceholderResourcePack(this.type); diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java index a094bcaf1a..e7a3823b1b 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java @@ -48,7 +48,7 @@ public abstract class ResourcePackManagerMixin { @Shadow @Final @Mutable - private Set providers; + public Set providers; @Shadow private Map profiles; @@ -101,8 +101,6 @@ private void handleAutoEnable(String profile, CallbackInfoReturnable ci } } - - @Inject(method = "disable", at = @At(value = "INVOKE", target = "Ljava/util/List;remove(Ljava/lang/Object;)Z")) private void handleAutoDisable(String profile, CallbackInfoReturnable cir, @Local List enabled) { if (ModResourcePackCreator.POST_CHANGE_HANDLE_REQUIRED.contains(profile)) { diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackProfileMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackProfileMixin.java index b59524aaa9..e3e35e3171 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackProfileMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackProfileMixin.java @@ -16,7 +16,6 @@ package net.fabricmc.fabric.mixin.resource.loader; -import java.util.Collections; import java.util.Set; import java.util.function.Predicate; @@ -56,6 +55,7 @@ abstract class ResourcePackProfileMixin implements FabricResourcePackProfile { private void onCreateResourcePack(CallbackInfoReturnable info) { ResourcePackSourceTracker.setSource(info.getReturnValue(), source); } + @Override public boolean isHidden() { return parentsPredicate != DEFAULT_PARENT_PREDICATE; From 50665fc91d1578a9e4547c2e24078e08dcea63cd Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Fri, 22 Dec 2023 11:02:53 +0900 Subject: [PATCH 04/23] Fix wrong variable in serialization code --- .../fabric/impl/resource/loader/ModResourcePackUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java index b7b8025eb9..0ea9620bce 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java @@ -127,7 +127,7 @@ public static String serializeMetadata(int packVersion, String description) { JsonObject pack = getMetadataPackJson(packVersion, new JsonPrimitive(description)); JsonObject metadata = new JsonObject(); metadata.add("pack", pack); - return GSON.toJson(pack); + return GSON.toJson(metadata); } public static Text getName(ModMetadata info) { From 689413fc04aca9b719f2ab5b0524428152272e51 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Fri, 22 Dec 2023 13:45:25 +0900 Subject: [PATCH 05/23] Hide packs in PackScreen and DatapackCommand --- .../resource/loader/FabricAbstractPack.java | 23 +++++++ .../loader/client/PackScreenMixin.java | 39 +++++++++++ ...esourcePackOrganizerAbstractPackMixin.java | 37 +++++++++++ ...bric-resource-loader-v0.client.mixins.json | 6 +- .../resource/loader/DatapackCommandMixin.java | 66 +++++++++++++++++++ .../fabric-resource-loader-v0/lang/en_us.json | 3 +- .../fabric-resource-loader-v0.mixins.json | 1 + .../src/main/resources/fabric.mod.json | 3 +- 8 files changed, 174 insertions(+), 4 deletions(-) create mode 100644 fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/FabricAbstractPack.java create mode 100644 fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/PackScreenMixin.java create mode 100644 fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerAbstractPackMixin.java create mode 100644 fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/FabricAbstractPack.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/FabricAbstractPack.java new file mode 100644 index 0000000000..e20bb63a95 --- /dev/null +++ b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/FabricAbstractPack.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.client.resource.loader; + +public interface FabricAbstractPack { + default boolean isHidden() { + return false; + } +} diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/PackScreenMixin.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/PackScreenMixin.java new file mode 100644 index 0000000000..0b0c59f3dd --- /dev/null +++ b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/PackScreenMixin.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.resource.loader.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.gui.screen.pack.PackListWidget; +import net.minecraft.client.gui.screen.pack.PackScreen; +import net.minecraft.client.gui.screen.pack.ResourcePackOrganizer; + +import net.fabricmc.fabric.impl.client.resource.loader.FabricAbstractPack; + +@Mixin(PackScreen.class) +public class PackScreenMixin { + @Inject(method = "method_29672", at = @At("HEAD"), cancellable = true) + private void hideHiddenPacks(PackListWidget packListWidget, String string, ResourcePackOrganizer.Pack pack, CallbackInfo ci) { + // (Fabric)AbstractPack is the only vanilla implementation of Pack, but we cast anyway. + if (pack instanceof FabricAbstractPack fabricAbstractPack && fabricAbstractPack.isHidden()) { + ci.cancel(); + } + } +} diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerAbstractPackMixin.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerAbstractPackMixin.java new file mode 100644 index 0000000000..b1fcfe6bad --- /dev/null +++ b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerAbstractPackMixin.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.resource.loader.client; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.resource.ResourcePackProfile; + +import net.fabricmc.fabric.impl.client.resource.loader.FabricAbstractPack; + +@Mixin(targets = "net/minecraft/client/gui/screen/pack/ResourcePackOrganizer$AbstractPack") +public class ResourcePackOrganizerAbstractPackMixin implements FabricAbstractPack { + @Shadow + @Final + private ResourcePackProfile profile; + + @Override + public boolean isHidden() { + return this.profile.isHidden(); + } +} diff --git a/fabric-resource-loader-v0/src/client/resources/fabric-resource-loader-v0.client.mixins.json b/fabric-resource-loader-v0/src/client/resources/fabric-resource-loader-v0.client.mixins.json index 9920bc5d27..b2e0d6e6ab 100644 --- a/fabric-resource-loader-v0/src/client/resources/fabric-resource-loader-v0.client.mixins.json +++ b/fabric-resource-loader-v0/src/client/resources/fabric-resource-loader-v0.client.mixins.json @@ -3,11 +3,13 @@ "package": "net.fabricmc.fabric.mixin.resource.loader.client", "compatibilityLevel": "JAVA_17", "client": [ - "VanillaResourcePackProviderMixin", "CreateWorldScreenMixin", "FontManagerMixin", "GameOptionsMixin", - "KeyedResourceReloadListenerClientMixin" + "KeyedResourceReloadListenerClientMixin", + "PackScreenMixin", + "ResourcePackOrganizerAbstractPackMixin", + "VanillaResourcePackProviderMixin" ], "injectors": { "defaultRequire": 1 diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java new file mode 100644 index 0000000000..fb2ee0c2f5 --- /dev/null +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.resource.loader; + +import java.util.Collection; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.resource.ResourcePackManager; +import net.minecraft.resource.ResourcePackProfile; +import net.minecraft.server.command.DatapackCommand; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.Text; + +/** + * Disables enabling/disabling internal data packs. + * Listing them is still allowed, but they do not appear in suggestions. + */ +@Mixin(DatapackCommand.class) +public class DatapackCommandMixin { + @Unique + private static final DynamicCommandExceptionType INTERNAL_PACK_EXCEPTION = new DynamicCommandExceptionType( + packName -> Text.stringifiedTranslatable("commands.datapack.fabric.internal", packName)); + + @Redirect(method = "method_13136", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourcePackManager;getEnabledNames()Ljava/util/Collection;")) + private static Collection filterEnabledPackSuggestions(ResourcePackManager dataPackManager) { + return dataPackManager.getEnabledProfiles().stream().filter(Predicate.not(ResourcePackProfile::isHidden)).map(ResourcePackProfile::getName).toList(); + } + + @WrapOperation(method = "method_13120", at = @At(value = "INVOKE", target = "Ljava/util/stream/Stream;filter(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;", ordinal = 0)) + private static Stream filterDisabledPackSuggestions(Stream instance, Predicate predicate, Operation> original) { + return original.call(instance, predicate).filter(Predicate.not(ResourcePackProfile::isHidden)); + } + + @Inject(method = "getPackContainer", at = @At(value = "INVOKE", target = "Ljava/util/Collection;contains(Ljava/lang/Object;)Z", shift = At.Shift.BEFORE)) + private static void errorOnInternalPack(CommandContext context, String name, boolean enable, CallbackInfoReturnable cir, @Local ResourcePackProfile profile) throws CommandSyntaxException { + if (profile.isHidden()) throw INTERNAL_PACK_EXCEPTION.create(name); + } +} diff --git a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/en_us.json b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/en_us.json index 50b4a32327..892c6fe421 100644 --- a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/en_us.json +++ b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/en_us.json @@ -4,5 +4,6 @@ "pack.source.builtinMod": "built-in: %s", "pack.name.fabricMod": "Fabric Mod \"%s\"", "pack.name.fabricMods": "Fabric Mods", - "pack.name.fabricMod.subPack": "Fabric Mod \"%s\" (%s)" + "pack.name.fabricMod.subPack": "Fabric Mod \"%s\" (%s)", + "commands.datapack.fabric.internal": "Cannot enable or disable Fabric internal pack \"%s\"." } diff --git a/fabric-resource-loader-v0/src/main/resources/fabric-resource-loader-v0.mixins.json b/fabric-resource-loader-v0/src/main/resources/fabric-resource-loader-v0.mixins.json index 4d85f95810..cf05b13a5e 100644 --- a/fabric-resource-loader-v0/src/main/resources/fabric-resource-loader-v0.mixins.json +++ b/fabric-resource-loader-v0/src/main/resources/fabric-resource-loader-v0.mixins.json @@ -3,6 +3,7 @@ "package": "net.fabricmc.fabric.mixin.resource.loader", "compatibilityLevel": "JAVA_17", "mixins": [ + "DatapackCommandMixin", "KeyedResourceReloadListenerMixin", "LifecycledResourceManagerImplMixin", "MinecraftServerMixin", diff --git a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json index 3137226e78..aca0954666 100644 --- a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json +++ b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json @@ -30,7 +30,8 @@ "custom": { "fabric-api:module-lifecycle": "stable", "loom:injected_interfaces": { - "net/minecraft/class_3288": ["net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile"] + "net/minecraft/class_3288": ["net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile"], + "net/minecraft/class_5369$class_5372": ["net/fabricmc/fabric/impl/client/resource/loader/FabricAbstractPack"] } } } From 9cb6b316054798c8e24c9d2c524b2fbc38550163 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Fri, 22 Dec 2023 13:55:22 +0900 Subject: [PATCH 06/23] Apparently Japanese people aren't alone in having their currency signs used as special chars... --- fabric-resource-loader-v0/src/main/resources/fabric.mod.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json index aca0954666..da58f232ce 100644 --- a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json +++ b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json @@ -31,7 +31,7 @@ "fabric-api:module-lifecycle": "stable", "loom:injected_interfaces": { "net/minecraft/class_3288": ["net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile"], - "net/minecraft/class_5369$class_5372": ["net/fabricmc/fabric/impl/client/resource/loader/FabricAbstractPack"] + "net/minecraft/class_5369\u0024class_5372": ["net/fabricmc/fabric/impl/client/resource/loader/FabricAbstractPack"] } } } From efe6941105b58d9fcdfc7e28898b317480076a4f Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Fri, 22 Dec 2023 21:17:35 +0900 Subject: [PATCH 07/23] Inject directly to Pack --- .../fabric/mixin/resource/loader/client/PackScreenMixin.java | 5 +---- fabric-resource-loader-v0/src/main/resources/fabric.mod.json | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/PackScreenMixin.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/PackScreenMixin.java index 0b0c59f3dd..2e477ea9fb 100644 --- a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/PackScreenMixin.java +++ b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/PackScreenMixin.java @@ -25,14 +25,11 @@ import net.minecraft.client.gui.screen.pack.PackScreen; import net.minecraft.client.gui.screen.pack.ResourcePackOrganizer; -import net.fabricmc.fabric.impl.client.resource.loader.FabricAbstractPack; - @Mixin(PackScreen.class) public class PackScreenMixin { @Inject(method = "method_29672", at = @At("HEAD"), cancellable = true) private void hideHiddenPacks(PackListWidget packListWidget, String string, ResourcePackOrganizer.Pack pack, CallbackInfo ci) { - // (Fabric)AbstractPack is the only vanilla implementation of Pack, but we cast anyway. - if (pack instanceof FabricAbstractPack fabricAbstractPack && fabricAbstractPack.isHidden()) { + if (pack.isHidden()) { ci.cancel(); } } diff --git a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json index da58f232ce..baec6bbf9e 100644 --- a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json +++ b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json @@ -31,7 +31,7 @@ "fabric-api:module-lifecycle": "stable", "loom:injected_interfaces": { "net/minecraft/class_3288": ["net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile"], - "net/minecraft/class_5369\u0024class_5372": ["net/fabricmc/fabric/impl/client/resource/loader/FabricAbstractPack"] + "net/minecraft/class_5369\u0024class_5371": ["net/fabricmc/fabric/impl/client/resource/loader/FabricAbstractPack"] } } } From df327959b566818c9566ee1c594179ab5e743891 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Sat, 23 Dec 2023 00:05:15 +0900 Subject: [PATCH 08/23] Add temporary logging, fix bug --- .../resource/loader/DatapackCommandMixin.java | 2 +- .../loader/ResourcePackManagerMixin.java | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java index fb2ee0c2f5..ec5b5b116a 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java @@ -61,6 +61,6 @@ private static Stream filterDisabledPackSuggestions(Stream< @Inject(method = "getPackContainer", at = @At(value = "INVOKE", target = "Ljava/util/Collection;contains(Ljava/lang/Object;)Z", shift = At.Shift.BEFORE)) private static void errorOnInternalPack(CommandContext context, String name, boolean enable, CallbackInfoReturnable cir, @Local ResourcePackProfile profile) throws CommandSyntaxException { - if (profile.isHidden()) throw INTERNAL_PACK_EXCEPTION.create(name); + if (profile.isHidden()) throw INTERNAL_PACK_EXCEPTION.create(profile.getName()); } } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java index e7a3823b1b..d2d8c8aa48 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java @@ -25,10 +25,13 @@ import com.google.common.base.Functions; import com.llamalad7.mixinextras.sugar.Local; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -45,6 +48,9 @@ @Mixin(ResourcePackManager.class) public abstract class ResourcePackManagerMixin { + @Unique + private static final Logger LOGGER = LoggerFactory.getLogger("ResourcePackManagerMixin"); + @Shadow @Final @Mutable @@ -79,11 +85,14 @@ public void construct(ResourcePackProvider[] resourcePackProviders, CallbackInfo @Inject(method = "buildEnabledProfiles", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/ImmutableList;copyOf(Ljava/util/Collection;)Lcom/google/common/collect/ImmutableList;", shift = At.Shift.BEFORE)) private void handleAutoEnableDisable(Collection enabledNames, CallbackInfoReturnable> cir, @Local List enabledAfterFirstRun) { Set currentlyEnabled = enabledAfterFirstRun.stream().map(ResourcePackProfile::getName).collect(Collectors.toSet()); + LOGGER.info("Currently enabled: {}", currentlyEnabled); enabledAfterFirstRun.removeIf(resourcePackProfile -> !resourcePackProfile.parentsEnabled(currentlyEnabled)); + LOGGER.info("After removal: {}", enabledAfterFirstRun.stream().map(ResourcePackProfile::getName).toList()); for (ResourcePackProfile profile : this.profiles.values()) { - if (profile.parentsEnabled(currentlyEnabled) && !enabledAfterFirstRun.contains(profile)) { + if (profile.isHidden() && profile.parentsEnabled(currentlyEnabled) && !enabledAfterFirstRun.contains(profile)) { profile.getInitialPosition().insert(enabledAfterFirstRun, profile, Functions.identity(), false); + LOGGER.info("Auto-enabled: {}, list: {}", profile.getName(), enabledAfterFirstRun.stream().map(ResourcePackProfile::getName).toList()); } } } @@ -94,8 +103,9 @@ private void handleAutoEnable(String profile, CallbackInfoReturnable ci Set currentlyEnabled = newlyEnabled.stream().map(ResourcePackProfile::getName).collect(Collectors.toSet()); for (ResourcePackProfile p : this.profiles.values()) { - if (p.parentsEnabled(currentlyEnabled) && !newlyEnabled.contains(p)) { + if (p.isHidden() && p.parentsEnabled(currentlyEnabled) && !newlyEnabled.contains(p)) { newlyEnabled.add(p); + LOGGER.info("Auto-enabled after enable {}: {}, prev enabled: {}", profile, p.getName(), currentlyEnabled); } } } @@ -105,7 +115,9 @@ private void handleAutoEnable(String profile, CallbackInfoReturnable ci private void handleAutoDisable(String profile, CallbackInfoReturnable cir, @Local List enabled) { if (ModResourcePackCreator.POST_CHANGE_HANDLE_REQUIRED.contains(profile)) { Set currentlyEnabled = enabled.stream().map(ResourcePackProfile::getName).collect(Collectors.toSet()); + LOGGER.info("Currently enabled: {}", currentlyEnabled); enabled.removeIf(p -> !p.parentsEnabled(currentlyEnabled)); + LOGGER.info("Auto-removal on disable {}: {}", profile, enabled.stream().map(ResourcePackProfile::getName).toList()); } } } From ea2b529f658baa21b95fdaa68e61154008293134 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Wed, 27 Dec 2023 22:59:41 +0900 Subject: [PATCH 09/23] Add proper sorting --- .../loader/ModResourcePackCreator.java | 3 ++ .../resource/loader/ModResourcePackUtil.java | 5 +++ .../loader/ResourcePackManagerMixin.java | 42 +++++++++++-------- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java index 5bb41fe16b..a9ef133073 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java @@ -43,6 +43,9 @@ public class ModResourcePackCreator implements ResourcePackProvider { private static final Predicate> BASE_PARENT = enabled -> enabled.contains(FABRIC); private static final Predicate> PROGRAMMER_ART_PARENT = enabled -> enabled.contains(FABRIC) && enabled.contains(PROGRAMMER_ART); private static final Predicate> HIGH_CONTRAST_PARENT = enabled -> enabled.contains(FABRIC) && enabled.contains(HIGH_CONTRAST); + /** + * This can be used to check if a pack profile is for mod-provided packs. + */ public static final ResourcePackSource RESOURCE_PACK_SOURCE = new ResourcePackSource() { @Override public Text decorate(Text packName) { diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java index 0ea9620bce..800c8f336b 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java @@ -154,6 +154,11 @@ public static DataConfiguration createDefaultDataConfiguration() { // This ensures that any built-in registered data packs by mods which needs to be enabled by default are // as the data pack screen automatically put any data pack as disabled except the Default data pack. for (ResourcePackProfile profile : moddedResourcePacks) { + if (profile.getSource() == ModResourcePackCreator.RESOURCE_PACK_SOURCE) { + enabled.add(profile.getName()); + continue; + } + try (ResourcePack pack = profile.createResourcePack()) { if (pack instanceof ModNioResourcePack && ((ModNioResourcePack) pack).getActivationType().isEnabledByDefault()) { enabled.add(profile.getName()); diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java index d2d8c8aa48..b561325c69 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java @@ -19,11 +19,11 @@ import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; +import java.util.ListIterator; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -import com.google.common.base.Functions; import com.llamalad7.mixinextras.sugar.Local; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,6 +44,7 @@ import net.minecraft.resource.ResourcePackSource; import net.minecraft.resource.ResourceType; +import net.fabricmc.fabric.impl.resource.loader.FabricResourcePackProfile; import net.fabricmc.fabric.impl.resource.loader.ModResourcePackCreator; @Mixin(ResourcePackManager.class) @@ -84,31 +85,38 @@ public void construct(ResourcePackProvider[] resourcePackProviders, CallbackInfo @Inject(method = "buildEnabledProfiles", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/ImmutableList;copyOf(Ljava/util/Collection;)Lcom/google/common/collect/ImmutableList;", shift = At.Shift.BEFORE)) private void handleAutoEnableDisable(Collection enabledNames, CallbackInfoReturnable> cir, @Local List enabledAfterFirstRun) { - Set currentlyEnabled = enabledAfterFirstRun.stream().map(ResourcePackProfile::getName).collect(Collectors.toSet()); - LOGGER.info("Currently enabled: {}", currentlyEnabled); - enabledAfterFirstRun.removeIf(resourcePackProfile -> !resourcePackProfile.parentsEnabled(currentlyEnabled)); - LOGGER.info("After removal: {}", enabledAfterFirstRun.stream().map(ResourcePackProfile::getName).toList()); - - for (ResourcePackProfile profile : this.profiles.values()) { - if (profile.isHidden() && profile.parentsEnabled(currentlyEnabled) && !enabledAfterFirstRun.contains(profile)) { - profile.getInitialPosition().insert(enabledAfterFirstRun, profile, Functions.identity(), false); - LOGGER.info("Auto-enabled: {}, list: {}", profile.getName(), enabledAfterFirstRun.stream().map(ResourcePackProfile::getName).toList()); - } - } + this.refreshAutoEnabledPacks(enabledAfterFirstRun); } - @Inject(method = "enable", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z")) + @Inject(method = "enable", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", shift = At.Shift.AFTER)) private void handleAutoEnable(String profile, CallbackInfoReturnable cir, @Local List newlyEnabled) { if (ModResourcePackCreator.POST_CHANGE_HANDLE_REQUIRED.contains(profile)) { - Set currentlyEnabled = newlyEnabled.stream().map(ResourcePackProfile::getName).collect(Collectors.toSet()); + this.refreshAutoEnabledPacks(newlyEnabled); + } + } + + @Unique + private void refreshAutoEnabledPacks(List enabledProfiles) { + LOGGER.info("Started with: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); + enabledProfiles.removeIf(FabricResourcePackProfile::isHidden); + LOGGER.info("Removed internal packs: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); + ListIterator it = enabledProfiles.listIterator(); + // LinkedHashSet for debug log sort, will switch to normal HashSet once finished + Set seen = new LinkedHashSet<>(); + + while (it.hasNext()) { + ResourcePackProfile profile = it.next(); + seen.add(profile.getName()); for (ResourcePackProfile p : this.profiles.values()) { - if (p.isHidden() && p.parentsEnabled(currentlyEnabled) && !newlyEnabled.contains(p)) { - newlyEnabled.add(p); - LOGGER.info("Auto-enabled after enable {}: {}, prev enabled: {}", profile, p.getName(), currentlyEnabled); + if (p.isHidden() && p.parentsEnabled(seen) && seen.add(p.getName())) { + it.add(p); + LOGGER.info("Auto-enabled {}, currently enabled: {}", p, seen); } } } + + LOGGER.info("Final: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); } @Inject(method = "disable", at = @At(value = "INVOKE", target = "Ljava/util/List;remove(Ljava/lang/Object;)Z")) From 0bf768663a0413075da88a0e0302f52c789a960f Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Thu, 28 Dec 2023 02:08:27 +0900 Subject: [PATCH 10/23] Improve logging --- .../fabric/mixin/resource/loader/ResourcePackManagerMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java index b561325c69..2e3e0b7154 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java @@ -111,7 +111,7 @@ private void refreshAutoEnabledPacks(List enabledProfiles) for (ResourcePackProfile p : this.profiles.values()) { if (p.isHidden() && p.parentsEnabled(seen) && seen.add(p.getName())) { it.add(p); - LOGGER.info("Auto-enabled {}, currently enabled: {}", p, seen); + LOGGER.info("cur @ {}, auto-enabled {}, currently enabled: {}", profile.getName(), p.getName(), seen); } } } From 2cac02c8940fcdcaf4df86d3af39f78a48a9cc76 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Thu, 28 Dec 2023 02:10:04 +0900 Subject: [PATCH 11/23] Fix duplicate name registration --- .../fabric/impl/resource/loader/ModResourcePackCreator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java index a9ef133073..405dc21740 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java @@ -115,7 +115,7 @@ private void registerModPack(Consumer consumer, @Nullable S ? Text.translatable("pack.name.fabricMod", pack.getFabricModMetadata().getName()) : Text.translatable("pack.name.fabricMod.subPack", pack.getFabricModMetadata().getName(), Text.translatable("resourcePack." + subPath + ".name")); ResourcePackProfile profile = ResourcePackProfile.create( - pack.getName(), + subPath == null ? pack.getName() : pack.getName() + "_" + subPath, displayName, subPath == null, new ModResourcePackFactory(pack), From 76ae3b008246cab336d963b8bb4deef07fcb1410 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Thu, 28 Dec 2023 20:33:50 +0900 Subject: [PATCH 12/23] Fix client pack handling --- .../resource/loader/FabricAbstractPack.java | 23 ------- .../client/GameOptionsWriteVisitorMixin.java | 61 +++++++++++++++++++ .../loader/client/PackScreenMixin.java | 36 ----------- ...esourcePackOrganizerAbstractPackMixin.java | 37 ----------- .../client/ResourcePackOrganizerMixin.java | 59 ++++++++++++++++++ ...bric-resource-loader-v0.client.mixins.json | 6 +- 6 files changed, 123 insertions(+), 99 deletions(-) delete mode 100644 fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/FabricAbstractPack.java create mode 100644 fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsWriteVisitorMixin.java delete mode 100644 fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/PackScreenMixin.java delete mode 100644 fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerAbstractPackMixin.java create mode 100644 fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerMixin.java diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/FabricAbstractPack.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/FabricAbstractPack.java deleted file mode 100644 index e20bb63a95..0000000000 --- a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/FabricAbstractPack.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.impl.client.resource.loader; - -public interface FabricAbstractPack { - default boolean isHidden() { - return false; - } -} diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsWriteVisitorMixin.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsWriteVisitorMixin.java new file mode 100644 index 0000000000..660d20aa13 --- /dev/null +++ b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsWriteVisitorMixin.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.resource.loader.client; + +import java.util.ArrayList; +import java.util.List; + +import com.llamalad7.mixinextras.sugar.Local; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.resource.ResourcePackManager; +import net.minecraft.resource.ResourcePackProfile; + +/** + * Mixins to the anonymous class in #write method. + */ +@Mixin(targets = "net/minecraft/client/option/GameOptions$3") +public class GameOptionsWriteVisitorMixin { + @Unique + private static List toPackListString(List packs) { + List copy = new ArrayList<>(packs.size()); + ResourcePackManager manager = MinecraftClient.getInstance().getResourcePackManager(); + + for (String pack : packs) { + ResourcePackProfile profile = manager.getProfile(pack); + + // Nonexistent pack profiles should be handled in the same way as vanilla + if (profile == null || !profile.isHidden()) copy.add(pack); + } + + return copy; + } + + @SuppressWarnings("unchecked") + @ModifyArg(method = "visitObject", at = @At(value = "INVOKE", target = "Ljava/util/function/Function;apply(Ljava/lang/Object;)Ljava/lang/Object;")) + private T skipHiddenPacks(T value, @Local String key) { + if ("resourcePacks".equals(key) && value instanceof List) { + return (T) toPackListString((List) value); + } + + return value; + } +} diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/PackScreenMixin.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/PackScreenMixin.java deleted file mode 100644 index 2e477ea9fb..0000000000 --- a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/PackScreenMixin.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.mixin.resource.loader.client; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import net.minecraft.client.gui.screen.pack.PackListWidget; -import net.minecraft.client.gui.screen.pack.PackScreen; -import net.minecraft.client.gui.screen.pack.ResourcePackOrganizer; - -@Mixin(PackScreen.class) -public class PackScreenMixin { - @Inject(method = "method_29672", at = @At("HEAD"), cancellable = true) - private void hideHiddenPacks(PackListWidget packListWidget, String string, ResourcePackOrganizer.Pack pack, CallbackInfo ci) { - if (pack.isHidden()) { - ci.cancel(); - } - } -} diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerAbstractPackMixin.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerAbstractPackMixin.java deleted file mode 100644 index b1fcfe6bad..0000000000 --- a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerAbstractPackMixin.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.mixin.resource.loader.client; - -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import net.minecraft.resource.ResourcePackProfile; - -import net.fabricmc.fabric.impl.client.resource.loader.FabricAbstractPack; - -@Mixin(targets = "net/minecraft/client/gui/screen/pack/ResourcePackOrganizer$AbstractPack") -public class ResourcePackOrganizerAbstractPackMixin implements FabricAbstractPack { - @Shadow - @Final - private ResourcePackProfile profile; - - @Override - public boolean isHidden() { - return this.profile.isHidden(); - } -} diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerMixin.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerMixin.java new file mode 100644 index 0000000000..79327d193e --- /dev/null +++ b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerMixin.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.resource.loader.client; + +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.gui.screen.pack.ResourcePackOrganizer; +import net.minecraft.resource.ResourcePackManager; +import net.minecraft.resource.ResourcePackProfile; + +@Mixin(ResourcePackOrganizer.class) +public class ResourcePackOrganizerMixin { + @Shadow + @Final + List enabledPacks; + + @Shadow + @Final + List disabledPacks; + + /** + * Do not list hidden packs in either enabledPacks or disabledPacks. + * They are managed entirely by ResourcePackManager on save, and are invisible to client. + */ + @Inject(method = "", at = @At("TAIL")) + private void removeHiddenPacksInit(Runnable updateCallback, Function iconIdSupplier, ResourcePackManager resourcePackManager, Consumer applier, CallbackInfo ci) { + this.enabledPacks.removeIf(ResourcePackProfile::isHidden); + this.disabledPacks.removeIf(ResourcePackProfile::isHidden); + } + + @Inject(method = "refresh", at = @At("TAIL")) + private void removeHiddenPacksRefresh(CallbackInfo ci) { + this.enabledPacks.removeIf(ResourcePackProfile::isHidden); + this.disabledPacks.removeIf(ResourcePackProfile::isHidden); + } +} diff --git a/fabric-resource-loader-v0/src/client/resources/fabric-resource-loader-v0.client.mixins.json b/fabric-resource-loader-v0/src/client/resources/fabric-resource-loader-v0.client.mixins.json index b2e0d6e6ab..8e7b6d57dc 100644 --- a/fabric-resource-loader-v0/src/client/resources/fabric-resource-loader-v0.client.mixins.json +++ b/fabric-resource-loader-v0/src/client/resources/fabric-resource-loader-v0.client.mixins.json @@ -7,9 +7,9 @@ "FontManagerMixin", "GameOptionsMixin", "KeyedResourceReloadListenerClientMixin", - "PackScreenMixin", - "ResourcePackOrganizerAbstractPackMixin", - "VanillaResourcePackProviderMixin" + "ResourcePackOrganizerMixin", + "VanillaResourcePackProviderMixin", + "GameOptionsWriteVisitorMixin" ], "injectors": { "defaultRequire": 1 From 02e45d7c8e327c3021c8f53f12c204dc810c7f65 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Thu, 28 Dec 2023 20:41:00 +0900 Subject: [PATCH 13/23] Fix FMJ --- fabric-resource-loader-v0/src/main/resources/fabric.mod.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json index baec6bbf9e..3137226e78 100644 --- a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json +++ b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json @@ -30,8 +30,7 @@ "custom": { "fabric-api:module-lifecycle": "stable", "loom:injected_interfaces": { - "net/minecraft/class_3288": ["net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile"], - "net/minecraft/class_5369\u0024class_5371": ["net/fabricmc/fabric/impl/client/resource/loader/FabricAbstractPack"] + "net/minecraft/class_3288": ["net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile"] } } } From 94ad868941d8ae2ce65efb981134f4858aa5bca9 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Tue, 2 Jan 2024 21:31:07 +0900 Subject: [PATCH 14/23] Stop using interface injection for internal interface --- .../loader/client/GameOptionsWriteVisitorMixin.java | 4 +++- .../loader/client/ResourcePackOrganizerMixin.java | 10 ++++++---- .../impl/resource/loader/ModResourcePackCreator.java | 2 +- .../mixin/resource/loader/DatapackCommandMixin.java | 8 +++++--- .../resource/loader/ResourcePackManagerMixin.java | 8 +++++--- .../src/main/resources/fabric.mod.json | 5 +---- 6 files changed, 21 insertions(+), 16 deletions(-) diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsWriteVisitorMixin.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsWriteVisitorMixin.java index 660d20aa13..de47248030 100644 --- a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsWriteVisitorMixin.java +++ b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsWriteVisitorMixin.java @@ -29,6 +29,8 @@ import net.minecraft.resource.ResourcePackManager; import net.minecraft.resource.ResourcePackProfile; +import net.fabricmc.fabric.impl.resource.loader.FabricResourcePackProfile; + /** * Mixins to the anonymous class in #write method. */ @@ -43,7 +45,7 @@ private static List toPackListString(List packs) { ResourcePackProfile profile = manager.getProfile(pack); // Nonexistent pack profiles should be handled in the same way as vanilla - if (profile == null || !profile.isHidden()) copy.add(pack); + if (profile == null || !((FabricResourcePackProfile) profile).isHidden()) copy.add(pack); } return copy; diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerMixin.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerMixin.java index 79327d193e..5f14b14432 100644 --- a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerMixin.java +++ b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerMixin.java @@ -31,6 +31,8 @@ import net.minecraft.resource.ResourcePackManager; import net.minecraft.resource.ResourcePackProfile; +import net.fabricmc.fabric.impl.resource.loader.FabricResourcePackProfile; + @Mixin(ResourcePackOrganizer.class) public class ResourcePackOrganizerMixin { @Shadow @@ -47,13 +49,13 @@ public class ResourcePackOrganizerMixin { */ @Inject(method = "", at = @At("TAIL")) private void removeHiddenPacksInit(Runnable updateCallback, Function iconIdSupplier, ResourcePackManager resourcePackManager, Consumer applier, CallbackInfo ci) { - this.enabledPacks.removeIf(ResourcePackProfile::isHidden); - this.disabledPacks.removeIf(ResourcePackProfile::isHidden); + this.enabledPacks.removeIf(profile -> ((FabricResourcePackProfile) profile).isHidden()); + this.disabledPacks.removeIf(profile -> ((FabricResourcePackProfile) profile).isHidden()); } @Inject(method = "refresh", at = @At("TAIL")) private void removeHiddenPacksRefresh(CallbackInfo ci) { - this.enabledPacks.removeIf(ResourcePackProfile::isHidden); - this.disabledPacks.removeIf(ResourcePackProfile::isHidden); + this.enabledPacks.removeIf(profile -> ((FabricResourcePackProfile) profile).isHidden()); + this.disabledPacks.removeIf(profile -> ((FabricResourcePackProfile) profile).isHidden()); } } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java index 405dc21740..a09941a1e9 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java @@ -125,7 +125,7 @@ private void registerModPack(Consumer consumer, @Nullable S ); if (profile != null) { - profile.setParentsPredicate(parents); + ((FabricResourcePackProfile) profile).setParentsPredicate(parents); consumer.accept(profile); } } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java index ec5b5b116a..53191c806a 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java @@ -39,6 +39,8 @@ import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; +import net.fabricmc.fabric.impl.resource.loader.FabricResourcePackProfile; + /** * Disables enabling/disabling internal data packs. * Listing them is still allowed, but they do not appear in suggestions. @@ -51,16 +53,16 @@ public class DatapackCommandMixin { @Redirect(method = "method_13136", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourcePackManager;getEnabledNames()Ljava/util/Collection;")) private static Collection filterEnabledPackSuggestions(ResourcePackManager dataPackManager) { - return dataPackManager.getEnabledProfiles().stream().filter(Predicate.not(ResourcePackProfile::isHidden)).map(ResourcePackProfile::getName).toList(); + return dataPackManager.getEnabledProfiles().stream().filter(profile -> !((FabricResourcePackProfile) profile).isHidden()).map(ResourcePackProfile::getName).toList(); } @WrapOperation(method = "method_13120", at = @At(value = "INVOKE", target = "Ljava/util/stream/Stream;filter(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;", ordinal = 0)) private static Stream filterDisabledPackSuggestions(Stream instance, Predicate predicate, Operation> original) { - return original.call(instance, predicate).filter(Predicate.not(ResourcePackProfile::isHidden)); + return original.call(instance, predicate).filter(profile -> !((FabricResourcePackProfile) profile).isHidden()); } @Inject(method = "getPackContainer", at = @At(value = "INVOKE", target = "Ljava/util/Collection;contains(Ljava/lang/Object;)Z", shift = At.Shift.BEFORE)) private static void errorOnInternalPack(CommandContext context, String name, boolean enable, CallbackInfoReturnable cir, @Local ResourcePackProfile profile) throws CommandSyntaxException { - if (profile.isHidden()) throw INTERNAL_PACK_EXCEPTION.create(profile.getName()); + if (((FabricResourcePackProfile) profile).isHidden()) throw INTERNAL_PACK_EXCEPTION.create(profile.getName()); } } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java index 2e3e0b7154..5ad29a502e 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java @@ -98,7 +98,7 @@ private void handleAutoEnable(String profile, CallbackInfoReturnable ci @Unique private void refreshAutoEnabledPacks(List enabledProfiles) { LOGGER.info("Started with: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); - enabledProfiles.removeIf(FabricResourcePackProfile::isHidden); + enabledProfiles.removeIf(profile -> ((FabricResourcePackProfile) profile).isHidden()); LOGGER.info("Removed internal packs: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); ListIterator it = enabledProfiles.listIterator(); // LinkedHashSet for debug log sort, will switch to normal HashSet once finished @@ -109,7 +109,9 @@ private void refreshAutoEnabledPacks(List enabledProfiles) seen.add(profile.getName()); for (ResourcePackProfile p : this.profiles.values()) { - if (p.isHidden() && p.parentsEnabled(seen) && seen.add(p.getName())) { + FabricResourcePackProfile fp = (FabricResourcePackProfile) p; + + if (fp.isHidden() && fp.parentsEnabled(seen) && seen.add(p.getName())) { it.add(p); LOGGER.info("cur @ {}, auto-enabled {}, currently enabled: {}", profile.getName(), p.getName(), seen); } @@ -124,7 +126,7 @@ private void handleAutoDisable(String profile, CallbackInfoReturnable c if (ModResourcePackCreator.POST_CHANGE_HANDLE_REQUIRED.contains(profile)) { Set currentlyEnabled = enabled.stream().map(ResourcePackProfile::getName).collect(Collectors.toSet()); LOGGER.info("Currently enabled: {}", currentlyEnabled); - enabled.removeIf(p -> !p.parentsEnabled(currentlyEnabled)); + enabled.removeIf(p -> !((FabricResourcePackProfile) p).parentsEnabled(currentlyEnabled)); LOGGER.info("Auto-removal on disable {}: {}", profile, enabled.stream().map(ResourcePackProfile::getName).toList()); } } diff --git a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json index 3137226e78..b2987ac3c1 100644 --- a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json +++ b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json @@ -28,9 +28,6 @@ ], "accessWidener": "fabric-resource-loader-v0.accesswidener", "custom": { - "fabric-api:module-lifecycle": "stable", - "loom:injected_interfaces": { - "net/minecraft/class_3288": ["net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile"] - } + "fabric-api:module-lifecycle": "stable" } } From eb74aba467f323d4b048d125045e942a1af0180e Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Tue, 2 Jan 2024 21:33:11 +0900 Subject: [PATCH 15/23] Delete unused GroupResourcePack --- .../resource/loader/GroupResourcePack.java | 123 ------------------ 1 file changed, 123 deletions(-) delete mode 100644 fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/GroupResourcePack.java diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/GroupResourcePack.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/GroupResourcePack.java deleted file mode 100644 index f4c8981afd..0000000000 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/GroupResourcePack.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.impl.resource.loader; - -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - -import net.minecraft.resource.InputSupplier; -import net.minecraft.resource.NamespaceResourceManager; -import net.minecraft.resource.Resource; -import net.minecraft.resource.ResourcePack; -import net.minecraft.resource.ResourceType; -import net.minecraft.resource.metadata.ResourceMetadata; -import net.minecraft.util.Identifier; - -/** - * Represents a group resource pack, holds multiple resource packs as one. - */ -public abstract class GroupResourcePack implements ResourcePack { - protected final ResourceType type; - protected final List packs; - protected final Map> namespacedPacks = new Object2ObjectOpenHashMap<>(); - - public GroupResourcePack(ResourceType type, List packs) { - this.type = type; - this.packs = packs; - this.packs.forEach(pack -> pack.getNamespaces(this.type) - .forEach(namespace -> this.namespacedPacks.computeIfAbsent(namespace, value -> new ArrayList<>()) - .add(pack))); - } - - @Override - public InputSupplier open(ResourceType type, Identifier id) { - List packs = this.namespacedPacks.get(id.getNamespace()); - - if (packs != null) { - // Last to first, since higher priority packs are at the end - for (int i = packs.size() - 1; i >= 0; i--) { - ResourcePack pack = packs.get(i); - InputSupplier supplier = pack.open(type, id); - - if (supplier != null) { - return supplier; - } - } - } - - return null; - } - - @Override - public void findResources(ResourceType type, String namespace, String prefix, ResultConsumer consumer) { - List packs = this.namespacedPacks.get(namespace); - - if (packs == null) { - return; - } - - // First to last, since later calls override previously returned data - for (ResourcePack pack : packs) { - pack.findResources(type, namespace, prefix, consumer); - } - } - - @Override - public Set getNamespaces(ResourceType type) { - return this.namespacedPacks.keySet(); - } - - public void appendResources(ResourceType type, Identifier id, List resources) { - List packs = this.namespacedPacks.get(id.getNamespace()); - - if (packs == null) { - return; - } - - Identifier metadataId = NamespaceResourceManager.getMetadataPath(id); - - // Last to first, since higher priority packs are at the end - for (int i = packs.size() - 1; i >= 0; i--) { - ResourcePack pack = packs.get(i); - InputSupplier supplier = pack.open(type, id); - - if (supplier != null) { - InputSupplier metadataSupplier = () -> { - InputSupplier rawMetadataSupplier = pack.open(this.type, metadataId); - return rawMetadataSupplier != null ? NamespaceResourceManager.loadMetadata(rawMetadataSupplier) : ResourceMetadata.NONE; - }; - - resources.add(new Resource(pack, supplier, metadataSupplier)); - } - } - } - - public String getFullName() { - return this.getName() + " (" + this.packs.stream().map(ResourcePack::getName).collect(Collectors.joining(", ")) + ")"; - } - - @Override - public void close() { - this.packs.forEach(ResourcePack::close); - } -} From 683d6b764416e52f8c31e171503d07d8cb8adcea Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Tue, 2 Jan 2024 21:39:46 +0900 Subject: [PATCH 16/23] Move refreshAutoEnabledPacks to util --- .../loader/client/GameOptionsMixin.java | 2 +- .../resource/loader/ModResourcePackUtil.java | 31 +++++++++++++++++ .../loader/ResourcePackManagerMixin.java | 34 +++---------------- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsMixin.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsMixin.java index b9533c3f87..303d688955 100644 --- a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsMixin.java +++ b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsMixin.java @@ -99,7 +99,7 @@ private void onLoad(CallbackInfo ci) { for (ResourcePackProfile profile : profiles) { // Always add "Fabric Mods" pack to enabled resource packs. - if (profile.getSource() == ModResourcePackCreator.RESOURCE_PACK_SOURCE) { + if (profile.getName().equals(ModResourcePackCreator.FABRIC)) { resourcePacks.add(profile.getName()); continue; } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java index 800c8f336b..528cdf0fd0 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java @@ -23,7 +23,10 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; +import java.util.ListIterator; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -35,6 +38,8 @@ import com.google.gson.JsonPrimitive; import org.apache.commons.io.IOUtils; import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import net.minecraft.SharedConstants; import net.minecraft.resource.DataConfiguration; @@ -56,6 +61,7 @@ */ public final class ModResourcePackUtil { public static final Gson GSON = new Gson(); + private static final Logger LOGGER = LoggerFactory.getLogger(ModResourcePackUtil.class); private ModResourcePackUtil() { } @@ -81,6 +87,31 @@ public static void appendModResourcePacks(List packs, ResourceT } } + public static void refreshAutoEnabledPacks(List enabledProfiles, Map allProfiles) { + LOGGER.info("Started with: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); + enabledProfiles.removeIf(profile -> ((FabricResourcePackProfile) profile).isHidden()); + LOGGER.info("Removed internal packs: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); + ListIterator it = enabledProfiles.listIterator(); + // LinkedHashSet for debug log sort, will switch to normal HashSet once finished + Set seen = new LinkedHashSet<>(); + + while (it.hasNext()) { + ResourcePackProfile profile = it.next(); + seen.add(profile.getName()); + + for (ResourcePackProfile p : allProfiles.values()) { + FabricResourcePackProfile fp = (FabricResourcePackProfile) p; + + if (fp.isHidden() && fp.parentsEnabled(seen) && seen.add(p.getName())) { + it.add(p); + LOGGER.info("cur @ {}, auto-enabled {}, currently enabled: {}", profile.getName(), p.getName(), seen); + } + } + } + + LOGGER.info("Final: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); + } + public static boolean containsDefault(String filename, boolean modBundled) { return "pack.mcmeta".equals(filename) || (modBundled && "pack.png".equals(filename)); } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java index 5ad29a502e..7c71caf3e0 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java @@ -19,7 +19,6 @@ import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; -import java.util.ListIterator; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -46,9 +45,10 @@ import net.fabricmc.fabric.impl.resource.loader.FabricResourcePackProfile; import net.fabricmc.fabric.impl.resource.loader.ModResourcePackCreator; +import net.fabricmc.fabric.impl.resource.loader.ModResourcePackUtil; @Mixin(ResourcePackManager.class) -public abstract class ResourcePackManagerMixin { +public abstract class ResourcePackManagerMixin { @Unique private static final Logger LOGGER = LoggerFactory.getLogger("ResourcePackManagerMixin"); @@ -85,42 +85,16 @@ public void construct(ResourcePackProvider[] resourcePackProviders, CallbackInfo @Inject(method = "buildEnabledProfiles", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/ImmutableList;copyOf(Ljava/util/Collection;)Lcom/google/common/collect/ImmutableList;", shift = At.Shift.BEFORE)) private void handleAutoEnableDisable(Collection enabledNames, CallbackInfoReturnable> cir, @Local List enabledAfterFirstRun) { - this.refreshAutoEnabledPacks(enabledAfterFirstRun); + ModResourcePackUtil.refreshAutoEnabledPacks(enabledAfterFirstRun, this.profiles); } @Inject(method = "enable", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", shift = At.Shift.AFTER)) private void handleAutoEnable(String profile, CallbackInfoReturnable cir, @Local List newlyEnabled) { if (ModResourcePackCreator.POST_CHANGE_HANDLE_REQUIRED.contains(profile)) { - this.refreshAutoEnabledPacks(newlyEnabled); + ModResourcePackUtil.refreshAutoEnabledPacks(newlyEnabled, this.profiles); } } - @Unique - private void refreshAutoEnabledPacks(List enabledProfiles) { - LOGGER.info("Started with: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); - enabledProfiles.removeIf(profile -> ((FabricResourcePackProfile) profile).isHidden()); - LOGGER.info("Removed internal packs: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); - ListIterator it = enabledProfiles.listIterator(); - // LinkedHashSet for debug log sort, will switch to normal HashSet once finished - Set seen = new LinkedHashSet<>(); - - while (it.hasNext()) { - ResourcePackProfile profile = it.next(); - seen.add(profile.getName()); - - for (ResourcePackProfile p : this.profiles.values()) { - FabricResourcePackProfile fp = (FabricResourcePackProfile) p; - - if (fp.isHidden() && fp.parentsEnabled(seen) && seen.add(p.getName())) { - it.add(p); - LOGGER.info("cur @ {}, auto-enabled {}, currently enabled: {}", profile.getName(), p.getName(), seen); - } - } - } - - LOGGER.info("Final: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); - } - @Inject(method = "disable", at = @At(value = "INVOKE", target = "Ljava/util/List;remove(Ljava/lang/Object;)Z")) private void handleAutoDisable(String profile, CallbackInfoReturnable cir, @Local List enabled) { if (ModResourcePackCreator.POST_CHANGE_HANDLE_REQUIRED.contains(profile)) { From f45deb395f6c1d33a144834d66ed577c00b017b3 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Tue, 2 Jan 2024 21:48:08 +0900 Subject: [PATCH 17/23] Improve logging --- .../fabric/impl/resource/loader/ModResourcePackUtil.java | 8 ++++---- .../mixin/resource/loader/ResourcePackManagerMixin.java | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java index 528cdf0fd0..21f600651a 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java @@ -88,9 +88,9 @@ public static void appendModResourcePacks(List packs, ResourceT } public static void refreshAutoEnabledPacks(List enabledProfiles, Map allProfiles) { - LOGGER.info("Started with: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); + LOGGER.debug("[Fabric] Starting internal pack sorting with: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); enabledProfiles.removeIf(profile -> ((FabricResourcePackProfile) profile).isHidden()); - LOGGER.info("Removed internal packs: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); + LOGGER.debug("[Fabric] Removed all internal packs, result: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); ListIterator it = enabledProfiles.listIterator(); // LinkedHashSet for debug log sort, will switch to normal HashSet once finished Set seen = new LinkedHashSet<>(); @@ -104,12 +104,12 @@ public static void refreshAutoEnabledPacks(List enabledProf if (fp.isHidden() && fp.parentsEnabled(seen) && seen.add(p.getName())) { it.add(p); - LOGGER.info("cur @ {}, auto-enabled {}, currently enabled: {}", profile.getName(), p.getName(), seen); + LOGGER.debug("[Fabric] cur @ {}, auto-enabled {}, currently enabled: {}", profile.getName(), p.getName(), seen); } } } - LOGGER.info("Final: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); + LOGGER.debug("[Fabric] Final sorting result: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); } public static boolean containsDefault(String filename, boolean modBundled) { diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java index 7c71caf3e0..a1ec184366 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java @@ -99,9 +99,8 @@ private void handleAutoEnable(String profile, CallbackInfoReturnable ci private void handleAutoDisable(String profile, CallbackInfoReturnable cir, @Local List enabled) { if (ModResourcePackCreator.POST_CHANGE_HANDLE_REQUIRED.contains(profile)) { Set currentlyEnabled = enabled.stream().map(ResourcePackProfile::getName).collect(Collectors.toSet()); - LOGGER.info("Currently enabled: {}", currentlyEnabled); enabled.removeIf(p -> !((FabricResourcePackProfile) p).parentsEnabled(currentlyEnabled)); - LOGGER.info("Auto-removal on disable {}: {}", profile, enabled.stream().map(ResourcePackProfile::getName).toList()); + LOGGER.debug("[Fabric] Internal pack auto-removed upon disabling {}, result: {}", profile, enabled.stream().map(ResourcePackProfile::getName).toList()); } } } From fc1a71e4a3239e7ad73f7e5f94fc35890a300c90 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Tue, 2 Jan 2024 21:50:09 +0900 Subject: [PATCH 18/23] Make a few things private --- .../fabric/impl/resource/loader/PlaceholderResourcePack.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java index 98f8c98923..287cf11b07 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java @@ -38,8 +38,8 @@ import net.minecraft.util.Identifier; public record PlaceholderResourcePack(ResourceType type) implements ResourcePack { - public static final Text DESCRIPTION_TEXT = Text.translatable("pack.description.modResources"); - public static final JsonElement DESCRIPTION_JSON = TextCodecs.CODEC.encodeStart(JsonOps.INSTANCE, DESCRIPTION_TEXT).result().get(); + private static final Text DESCRIPTION_TEXT = Text.translatable("pack.description.modResources"); + private static final JsonElement DESCRIPTION_JSON = TextCodecs.CODEC.encodeStart(JsonOps.INSTANCE, DESCRIPTION_TEXT).result().get(); public JsonObject getMetadata() { return ModResourcePackUtil.getMetadataPackJson( From c0af7c982dcce741b41a98e43a33ecc181e1f3a5 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Tue, 2 Jan 2024 22:02:21 +0900 Subject: [PATCH 19/23] Use vanilla metadata serialization logic --- .../resource/loader/ModResourcePackUtil.java | 17 +++++++------- .../loader/PlaceholderResourcePack.java | 22 ++++++------------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java index 21f600651a..71a0b56142 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java @@ -33,9 +33,7 @@ import com.google.common.base.Charsets; import com.google.gson.Gson; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; import org.apache.commons.io.IOUtils; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -48,6 +46,7 @@ import net.minecraft.resource.ResourcePackProfile; import net.minecraft.resource.ResourceType; import net.minecraft.resource.featuretoggle.FeatureFlags; +import net.minecraft.resource.metadata.PackResourceMetadata; import net.minecraft.text.Text; import net.fabricmc.fabric.api.resource.ModResourcePack; @@ -147,15 +146,17 @@ public static InputStream openDefault(ModContainer container, ResourceType type, } } - public static JsonObject getMetadataPackJson(int packVersion, JsonElement description) { - JsonObject pack = new JsonObject(); - pack.addProperty("pack_format", packVersion); - pack.add("description", description); - return pack; + public static PackResourceMetadata getMetadataPack(int packVersion, Text description) { + return new PackResourceMetadata(description, packVersion, Optional.empty()); + } + + public static JsonObject getMetadataPackJson(int packVersion, Text description) { + return PackResourceMetadata.SERIALIZER.toJson(getMetadataPack(packVersion, description)); } public static String serializeMetadata(int packVersion, String description) { - JsonObject pack = getMetadataPackJson(packVersion, new JsonPrimitive(description)); + // This seems to be still manually deserialized + JsonObject pack = getMetadataPackJson(packVersion, Text.literal(description)); JsonObject metadata = new JsonObject(); metadata.add("pack", pack); return GSON.toJson(metadata); diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java index 287cf11b07..18b578cd3c 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/PlaceholderResourcePack.java @@ -21,9 +21,6 @@ import java.util.Collections; import java.util.Set; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.mojang.serialization.JsonOps; import org.apache.commons.io.IOUtils; import org.jetbrains.annotations.Nullable; @@ -32,19 +29,19 @@ import net.minecraft.resource.ResourcePack; import net.minecraft.resource.ResourcePackProfile; import net.minecraft.resource.ResourceType; +import net.minecraft.resource.metadata.PackResourceMetadata; +import net.minecraft.resource.metadata.ResourceMetadataMap; import net.minecraft.resource.metadata.ResourceMetadataReader; import net.minecraft.text.Text; -import net.minecraft.text.TextCodecs; import net.minecraft.util.Identifier; public record PlaceholderResourcePack(ResourceType type) implements ResourcePack { private static final Text DESCRIPTION_TEXT = Text.translatable("pack.description.modResources"); - private static final JsonElement DESCRIPTION_JSON = TextCodecs.CODEC.encodeStart(JsonOps.INSTANCE, DESCRIPTION_TEXT).result().get(); - public JsonObject getMetadata() { - return ModResourcePackUtil.getMetadataPackJson( + public PackResourceMetadata getMetadata() { + return ModResourcePackUtil.getMetadataPack( SharedConstants.getGameVersion().getResourceVersion(type), - DESCRIPTION_JSON + DESCRIPTION_TEXT ); } @@ -55,7 +52,7 @@ public InputSupplier openRoot(String... segments) { switch (segments[0]) { case "pack.mcmeta": return () -> { - String metadata = ModResourcePackUtil.GSON.toJson(getMetadata()); + String metadata = ModResourcePackUtil.GSON.toJson(PackResourceMetadata.SERIALIZER.toJson(getMetadata())); return IOUtils.toInputStream(metadata, StandardCharsets.UTF_8); }; case "pack.png": @@ -87,12 +84,7 @@ public Set getNamespaces(ResourceType type) { @Nullable @Override public T parseMetadata(ResourceMetadataReader metaReader) { - if ("pack".equals(metaReader.getKey())) { - return metaReader.fromJson(getMetadata()); - } - - // This pack does not have any overlays. - return null; + return ResourceMetadataMap.of(PackResourceMetadata.SERIALIZER, getMetadata()).get(metaReader); } @Override From 0d4d8ab2011a99dc2a689005020a3198ab201156 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Tue, 2 Jan 2024 22:47:07 +0900 Subject: [PATCH 20/23] Improve javadoc --- .../fabric/api/resource/package-info.java | 53 +++++++++++++------ .../loader/FabricResourcePackProfile.java | 8 ++- .../loader/ModResourcePackCreator.java | 3 ++ 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/api/resource/package-info.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/api/resource/package-info.java index fe46117940..95010b1262 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/api/resource/package-info.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/api/resource/package-info.java @@ -17,27 +17,48 @@ /** * The Resource Loader, version 0. * - *

Quick note about vocabulary in Resource Loader and Minecraft:

- *
    - *
  • Resource Pack refers to both client-sided resource pack and data pack.
  • - *
  • Virtual Resource Pack refers to a resource pack that may be generated at runtime, or simply doesn't exist directly on disk.
  • - *
  • Group Resource Pack refers to a virtual resource pack that groups multiple resource packs together.
  • - *
- *

+ *

Quick note about vocabulary in Minecraft:

+ *

Resource Pack refers to both client-sided resource pack and data pack.

* *

Modded Resource Pack Handling

- *

The Resource Loader will create a resource pack for each mod that provides resources in {@code assets} or {@code data} - * sub-directories. - * Those mod resource packs are grouped into a single always-enabled group resource pack which is shown in the resource pack screen.

+ *

There are two types of resource packs that mods can provide.

+ * + *

Bundled Resource Pack

+ *

Mods can "bundle" resource packs with the mod by putting files inside the {@code assets} or {@code data} + * sub-directories of the {@code resources} directory. They are always enabled, initially loaded after the vanilla pack, + * and cannot be disabled. Individual mods' packs are hidden to users in the Resource Pack option screen or the {@code /datapack} + * command. Instead, a placeholder pack, named "Fabric Mods", will be displayed. This pack, with the ID {@code fabric}, provides + * no resource itself; it is merely a marker used internally.

* *

Built-in Mod Resource Pack

- *

The Resource Loader adds manually registered mod resource packs. Those resource packs are registered with - * {@link net.fabricmc.fabric.api.resource.ResourceManagerHelper#registerBuiltinResourcePack(net.minecraft.util.Identifier, net.fabricmc.loader.api.ModContainer, net.fabricmc.fabric.api.resource.ResourcePackActivationType)}

+ *

The Resource Loader adds manually registered mod resource packs. Those resource packs are located inside the + * {@code resources/resourcepacks/} directory. For example, a built-in data pack with the ID {@code example:test} should be placed + * under {@code resources/resourcepacks/test/data/}. The packs are then registered with + * {@link net.fabricmc.fabric.api.resource.ResourceManagerHelper#registerBuiltinResourcePack(net.minecraft.util.Identifier, net.fabricmc.loader.api.ModContainer, net.fabricmc.fabric.api.resource.ResourcePackActivationType)}. + * Users can manually enable or disable the packs, unless it is specified to be always enabled.

+ * + *

Programmer Art and High Contrast Support

+ *

Bundled resource packs support Programmer Art and High Contrast vanilla resource packs. Simply place assets + * under {@code resources/programmer_art/assets/} or {@code resources/high_contrast/assets/}, respectively. + * Internally, these are treated as a separate internal pack, loaded just after the respective vanilla pack. + * Toggling the vanilla packs automatically toggles the bundled ones as well; you cannot separately enable or disable them.

+ * + *

Example

+ *

Mod A ({@code mod_a} provides a bundled resource pack with both Programmer Art and High Contrast support. + * Mod B ({@code mod_b}) provides a bundled resource pack and one built-in resource pack, Extra ({@code mod_b:extra}). + * When neither the Programmer Art nor High Contrast is enabled, the user sees "Vanilla", "Fabric Mods", and "Extra" in the + * Resource Packs screen. Internally, between Fabric Mods and Extra packs, two hidden packs exist: {@code mod_a} and {@code mod_b}.

+ * + *

Suppose the user then enables both the Programmer Art and High Contrast, and the Resource Packs screen lists + * "Vanilla", "Fabric", Programmer Art, "Extra", and High Contrast. Internally, there are 4 hidden packs:

+ * + *
    + *
  • {@code mod_a} and {@code mod_b} between "Fabric" and Programmer Art.
  • + *
  • {@code mod_a_programmer_art}, containing Mod A's Programmer Art assets, just after Programmer Art pack.
  • + *
  • {@code mod_a_high_contrast}, containing Mod A's High Contrast assets, just after High Contrast pack.
  • + *
* - *

Vanilla Built-in Resource Packs

- *

The Resource Loader will inject resources into the Programmer Art and High Contrast resource packs for each mod - * that provides resources in the {@code programmer_art} or {@code high_contrast} top-level directory of the mod - * whose structure is similar to a normal resource pack.

+ *

Note that while the current behavior is to sort bundled resource packs by mod ID in descending order (A to Z), this may change over time.

* *

Resource Reload Listener

*

The Resource Loader allows mods to register resource reload listeners through diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java index 9d0b1308f7..e419ca2fbf 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java @@ -20,9 +20,13 @@ import java.util.function.Predicate; /** - * Interface injected to ResourcePackProfile. + * Fabric addition to ResourcePackProfile. + * @see ModResourcePackCreator */ public interface FabricResourcePackProfile { + /** + * Returns whether the pack is internal and hidden from end users. + */ default boolean isHidden() { return false; } @@ -30,7 +34,7 @@ default boolean isHidden() { /** * Returns whether every parent is enabled. If this is not empty, the pack's status * is synced to that of the parent pack(s), where the pack gets enabled if and only - * if each of the parent is enabled. + * if each of the parent is enabled. Note that non-Fabric packs always return {@code true}. * * @return whether every parent is enabled. */ diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java index a09941a1e9..f34fea7a9d 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java @@ -36,6 +36,9 @@ * Represents a resource pack provider for mods and built-in mods resource packs. */ public class ModResourcePackCreator implements ResourcePackProvider { + /** + * The ID of the root resource pack profile for bundled packs. + */ public static final String FABRIC = "fabric"; private static final String PROGRAMMER_ART = "programmer_art"; private static final String HIGH_CONTRAST = "high_contrast"; From 2c92a178a135e3068cd9031618bbd287fd5f166b Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Wed, 3 Jan 2024 00:09:50 +0900 Subject: [PATCH 21/23] Add junit test --- .../loader/ModResourcePackCreator.java | 10 +- .../loader/unit/ModResourcePackUtilTests.java | 248 ++++++++++++++++++ .../loader/BuiltinResourcePackTestMod.java | 28 -- 3 files changed, 255 insertions(+), 31 deletions(-) create mode 100644 fabric-resource-loader-v0/src/test/java/net/fabricmc/fabric/test/resource/loader/unit/ModResourcePackUtilTests.java diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java index f34fea7a9d..3d6fefbfb6 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java @@ -23,6 +23,7 @@ import java.util.function.Predicate; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.VisibleForTesting; import net.minecraft.resource.ResourcePackProfile; import net.minecraft.resource.ResourcePackProvider; @@ -43,9 +44,12 @@ public class ModResourcePackCreator implements ResourcePackProvider { private static final String PROGRAMMER_ART = "programmer_art"; private static final String HIGH_CONTRAST = "high_contrast"; public static final Set POST_CHANGE_HANDLE_REQUIRED = Set.of(FABRIC, PROGRAMMER_ART, HIGH_CONTRAST); - private static final Predicate> BASE_PARENT = enabled -> enabled.contains(FABRIC); - private static final Predicate> PROGRAMMER_ART_PARENT = enabled -> enabled.contains(FABRIC) && enabled.contains(PROGRAMMER_ART); - private static final Predicate> HIGH_CONTRAST_PARENT = enabled -> enabled.contains(FABRIC) && enabled.contains(HIGH_CONTRAST); + @VisibleForTesting + public static final Predicate> BASE_PARENT = enabled -> enabled.contains(FABRIC); + @VisibleForTesting + public static final Predicate> PROGRAMMER_ART_PARENT = enabled -> enabled.contains(FABRIC) && enabled.contains(PROGRAMMER_ART); + @VisibleForTesting + public static final Predicate> HIGH_CONTRAST_PARENT = enabled -> enabled.contains(FABRIC) && enabled.contains(HIGH_CONTRAST); /** * This can be used to check if a pack profile is for mod-provided packs. */ diff --git a/fabric-resource-loader-v0/src/test/java/net/fabricmc/fabric/test/resource/loader/unit/ModResourcePackUtilTests.java b/fabric-resource-loader-v0/src/test/java/net/fabricmc/fabric/test/resource/loader/unit/ModResourcePackUtilTests.java new file mode 100644 index 0000000000..3cc04b5fe5 --- /dev/null +++ b/fabric-resource-loader-v0/src/test/java/net/fabricmc/fabric/test/resource/loader/unit/ModResourcePackUtilTests.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.resource.loader.unit; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.function.Predicate; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import net.minecraft.Bootstrap; +import net.minecraft.SharedConstants; +import net.minecraft.resource.ResourcePackProfile; + +import net.fabricmc.fabric.impl.resource.loader.FabricResourcePackProfile; +import net.fabricmc.fabric.impl.resource.loader.ModResourcePackCreator; +import net.fabricmc.fabric.impl.resource.loader.ModResourcePackUtil; + +public class ModResourcePackUtilTests { + private static final Gson GSON = new Gson(); + + @BeforeAll + static void beforeAll() { + SharedConstants.createGameVersion(); + Bootstrap.initialize(); + } + + @Test + void testRefreshAutoEnabledPacks() { + // Vanilla uses tree map, and we test the behavior + Map profiles = new TreeMap<>(); + Map modAProfiles = new TreeMap<>(); + Map modBProfiles = new TreeMap<>(); + Map allProfiles = new TreeMap<>(); + ResourcePackProfile vanilla = mockProfile(profiles, "vanilla", null); + ResourcePackProfile fabric = mockProfile(profiles, ModResourcePackCreator.FABRIC, null); + ResourcePackProfile modA = mockProfile(modAProfiles, "mod_a", ModResourcePackCreator.BASE_PARENT); + ResourcePackProfile modAProg = mockProfile(modAProfiles, "mod_a_programmer_art", ModResourcePackCreator.PROGRAMMER_ART_PARENT); + ResourcePackProfile modAHigh = mockProfile(modAProfiles, "mod_a_high_contrast", ModResourcePackCreator.HIGH_CONTRAST_PARENT); + ResourcePackProfile modB = mockProfile(modBProfiles, "mod_b", ModResourcePackCreator.BASE_PARENT); + ResourcePackProfile modBProg = mockProfile(modBProfiles, "mod_b_programmer_art", ModResourcePackCreator.PROGRAMMER_ART_PARENT); + ResourcePackProfile modBHigh = mockProfile(modBProfiles, "mod_b_high_contrast", ModResourcePackCreator.HIGH_CONTRAST_PARENT); + ResourcePackProfile programmerArt = mockProfile(profiles, "programmer_art", null); + ResourcePackProfile highContrast = mockProfile(profiles, "high_contrast", null); + ResourcePackProfile userPackA = mockProfile(profiles, "user_pack_a", null); + ResourcePackProfile userPackB = mockProfile(profiles, "user_pack_b", null); + modAProfiles.putAll(profiles); + modBProfiles.putAll(profiles); + allProfiles.putAll(modAProfiles); + allProfiles.putAll(modBProfiles); + + testRefreshAutoEnabledPacks( + profiles, + List.of(vanilla, fabric), + List.of(vanilla, fabric), + "keep (no mods)" + ); + testRefreshAutoEnabledPacks( + profiles, + List.of(vanilla, fabric, userPackA), + List.of(vanilla, fabric, userPackA), + "keep (no mods, keep user pack)" + ); + testRefreshAutoEnabledPacks( + modAProfiles, + List.of(vanilla, fabric, modA), + List.of(vanilla, fabric, modA), + "keep (mod A only)" + ); + testRefreshAutoEnabledPacks( + modAProfiles, + List.of(vanilla, fabric, modA, programmerArt, modAProg), + List.of(vanilla, fabric, modA, programmerArt, modAProg), + "keep (programmer_art)" + ); + testRefreshAutoEnabledPacks( + allProfiles, + List.of(vanilla, fabric, modA, modB, programmerArt, modAProg, modBProg), + List.of(vanilla, fabric, modA, modB, programmerArt, modAProg, modBProg), + "keep (mod A and mod B, programmer_art)" + ); + testRefreshAutoEnabledPacks( + allProfiles, + List.of(vanilla, fabric, modA, modB, programmerArt, modAProg, modBProg, highContrast, modAHigh, modBHigh), + List.of(vanilla, fabric, modA, modB, programmerArt, modAProg, modBProg, highContrast, modAHigh, modBHigh), + "keep (mod A and mod B, both)" + ); + testRefreshAutoEnabledPacks( + allProfiles, + List.of(vanilla, fabric, modA, modB, highContrast, modAHigh, modBHigh, programmerArt, modAProg, modBProg), + List.of(vanilla, fabric, modA, modB, highContrast, modAHigh, modBHigh, programmerArt, modAProg, modBProg), + "keep (remembers programmer_art-high_contrast order)" + ); + testRefreshAutoEnabledPacks( + modAProfiles, + List.of(vanilla, fabric), + List.of(vanilla, fabric, modA), + "fix (adding missing mods)" + ); + testRefreshAutoEnabledPacks( + allProfiles, + List.of(vanilla, fabric, userPackA), + List.of(vanilla, fabric, modA, modB, userPackA), + "fix (adding missing mods at the right place)" + ); + testRefreshAutoEnabledPacks( + allProfiles, + List.of(vanilla, fabric, modB, modA), + List.of(vanilla, fabric, modA, modB), + "fix (mod A and B, sorting)" + ); + testRefreshAutoEnabledPacks( + modAProfiles, + List.of(vanilla, fabric, userPackB, modA, userPackA), + List.of(vanilla, fabric, modA, userPackB, userPackA), + "fix (user pack goes last)" + ); + testRefreshAutoEnabledPacks( + modAProfiles, + List.of(vanilla, fabric, modA, programmerArt), + List.of(vanilla, fabric, modA, programmerArt, modAProg), + "fix (adding 1 met dep)" + ); + testRefreshAutoEnabledPacks( + modBProfiles, + List.of(vanilla, fabric, modB, highContrast), + List.of(vanilla, fabric, modB, highContrast, modBHigh), + "fix (adding 1 met dep, part 2)" + ); + testRefreshAutoEnabledPacks( + modAProfiles, + List.of(vanilla, fabric, modA, programmerArt, highContrast), + List.of(vanilla, fabric, modA, programmerArt, modAProg, highContrast, modAHigh), + "fix (adding 2 met deps)" + ); + testRefreshAutoEnabledPacks( + modAProfiles, + List.of(vanilla, fabric, modA, programmerArt, modAProg, highContrast), + List.of(vanilla, fabric, modA, programmerArt, modAProg, highContrast, modAHigh), + "fix (adding 2 met deps + preexisting)" + ); + testRefreshAutoEnabledPacks( + modAProfiles, + List.of(vanilla, fabric, modA, modAProg, modAHigh), + List.of(vanilla, fabric, modA), + "fix (removing 2 unmet deps)" + ); + testRefreshAutoEnabledPacks( + modAProfiles, + List.of(vanilla, fabric, modA, programmerArt, modAProg, modAHigh), + List.of(vanilla, fabric, modA, programmerArt, modAProg), + "fix (removing 1 unmet dep)" + ); + testRefreshAutoEnabledPacks( + modBProfiles, + List.of(vanilla, fabric, modB, highContrast, modBProg, modBHigh), + List.of(vanilla, fabric, modB, highContrast, modBHigh), + "fix (removing 1 unmet dep, part 2)" + ); + testRefreshAutoEnabledPacks( + modAProfiles, + List.of(vanilla, fabric, modAProg, programmerArt, modA), + List.of(vanilla, fabric, modA, programmerArt, modAProg), + "reorder (bundled comes just after parents)" + ); + testRefreshAutoEnabledPacks( + modAProfiles, + List.of(vanilla, fabric, modAProg, userPackA, programmerArt, modA, userPackB), + List.of(vanilla, fabric, modA, userPackA, programmerArt, modAProg, userPackB), + "reorder (keep user pack order)" + ); + testRefreshAutoEnabledPacks( + modAProfiles, + List.of(vanilla, fabric, userPackB, modA, programmerArt, userPackA, modAProg), + List.of(vanilla, fabric, modA, userPackB, programmerArt, modAProg, userPackA), + "reorder (no user pack between parent-bundled)" + ); + } + + private ResourcePackProfile mockProfile(Map profiles, String id, @Nullable Predicate> parents) { + ResourcePackProfile profile = ResourcePackProfile.of( + id, + null, + false, + null, + null, + null, + false, + ModResourcePackCreator.RESOURCE_PACK_SOURCE + ); + + if (parents != null) ((FabricResourcePackProfile) profile).setParentsPredicate(parents); + + profiles.put(id, profile); + return profile; + } + + private void testRefreshAutoEnabledPacks(Map profiles, List before, List after, String reason) { + List processed = new ArrayList<>(before); + ModResourcePackUtil.refreshAutoEnabledPacks(processed, profiles); + assertEquals( + after.stream().map(ResourcePackProfile::getName).toList(), + processed.stream().map(ResourcePackProfile::getName).toList(), + () -> "Testing %s; input %s".formatted(reason, before.stream().map(ResourcePackProfile::getName).toList()) + ); + } + + @Test + void testSerializeMetadata() { + // Test various metadata serialization issues (#2407) + testMetadataSerialization(""); + testMetadataSerialization("Quotes: \"\" \""); + testMetadataSerialization("Backslash: \\ \\\\"); + } + + private void testMetadataSerialization(String description) throws JsonParseException { + String metadata = ModResourcePackUtil.serializeMetadata(1, description); + JsonObject json = assertDoesNotThrow(() -> GSON.fromJson(metadata, JsonObject.class), () -> "Failed to serialize " + description); + + String parsedDescription = json.get("pack").getAsJsonObject().get("description").getAsString(); + assertEquals(description, parsedDescription, "Parsed description differs from original one"); + } +} diff --git a/fabric-resource-loader-v0/src/testmod/java/net/fabricmc/fabric/test/resource/loader/BuiltinResourcePackTestMod.java b/fabric-resource-loader-v0/src/testmod/java/net/fabricmc/fabric/test/resource/loader/BuiltinResourcePackTestMod.java index 02ce7fd79f..a7257c1b28 100644 --- a/fabric-resource-loader-v0/src/testmod/java/net/fabricmc/fabric/test/resource/loader/BuiltinResourcePackTestMod.java +++ b/fabric-resource-loader-v0/src/testmod/java/net/fabricmc/fabric/test/resource/loader/BuiltinResourcePackTestMod.java @@ -16,9 +16,6 @@ package net.fabricmc.fabric.test.resource.loader; -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,7 +25,6 @@ import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; import net.fabricmc.fabric.api.resource.ResourcePackActivationType; -import net.fabricmc.fabric.impl.resource.loader.ModResourcePackUtil; import net.fabricmc.loader.api.FabricLoader; public class BuiltinResourcePackTestMod implements ModInitializer { @@ -36,8 +32,6 @@ public class BuiltinResourcePackTestMod implements ModInitializer { private static final Logger LOGGER = LoggerFactory.getLogger(BuiltinResourcePackTestMod.class); - private static final Gson GSON = new Gson(); - @Override public void onInitialize() { // Should always be present as it's **this** mod. @@ -49,27 +43,5 @@ public void onInitialize() { .map(container -> ResourceManagerHelper.registerBuiltinResourcePack(new Identifier(MODID, "test2"), container, ResourcePackActivationType.NORMAL)) .filter(success -> !success).ifPresent(success -> LOGGER.warn("Could not register built-in resource pack.")); - - // Test various metadata serialization issues (#2407) - testMetadataSerialization(""); - testMetadataSerialization("Quotes: \"\" \""); - testMetadataSerialization("Backslash: \\ \\\\"); - } - - private void testMetadataSerialization(String description) { - String metadata = ModResourcePackUtil.serializeMetadata(1, description); - JsonObject json; - - try { - json = GSON.fromJson(metadata, JsonObject.class); - } catch (JsonParseException exc) { - throw new AssertionError("Metadata parsing test for description \"%s\" failed".formatted(description), exc); - } - - String parsedDescription = json.get("pack").getAsJsonObject().get("description").getAsString(); - - if (!description.equals(parsedDescription)) { - throw new AssertionError("Metadata parsing test for description failed: expected \"%s\", got \"%s\"".formatted(description, parsedDescription)); - } } } From a5e12d9e657c4b990e91631ac7e1bdec876b7294 Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Wed, 17 Jan 2024 22:21:33 +0900 Subject: [PATCH 22/23] Some final refactors --- .../loader/client/GameOptionsWriteVisitorMixin.java | 2 +- .../loader/client/ResourcePackOrganizerMixin.java | 8 ++++---- .../impl/resource/loader/FabricResourcePackProfile.java | 6 +++--- .../impl/resource/loader/ModResourcePackCreator.java | 2 +- .../fabric/impl/resource/loader/ModResourcePackUtil.java | 5 ++--- .../mixin/resource/loader/DatapackCommandMixin.java | 6 +++--- .../mixin/resource/loader/ResourcePackManagerMixin.java | 2 +- .../mixin/resource/loader/ResourcePackProfileMixin.java | 6 +++--- .../resource/loader/unit/ModResourcePackUtilTests.java | 2 +- 9 files changed, 19 insertions(+), 20 deletions(-) diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsWriteVisitorMixin.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsWriteVisitorMixin.java index de47248030..0563ad2a45 100644 --- a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsWriteVisitorMixin.java +++ b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/GameOptionsWriteVisitorMixin.java @@ -45,7 +45,7 @@ private static List toPackListString(List packs) { ResourcePackProfile profile = manager.getProfile(pack); // Nonexistent pack profiles should be handled in the same way as vanilla - if (profile == null || !((FabricResourcePackProfile) profile).isHidden()) copy.add(pack); + if (profile == null || !((FabricResourcePackProfile) profile).fabric_isHidden()) copy.add(pack); } return copy; diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerMixin.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerMixin.java index 5f14b14432..d6444d83c6 100644 --- a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerMixin.java +++ b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/ResourcePackOrganizerMixin.java @@ -49,13 +49,13 @@ public class ResourcePackOrganizerMixin { */ @Inject(method = "", at = @At("TAIL")) private void removeHiddenPacksInit(Runnable updateCallback, Function iconIdSupplier, ResourcePackManager resourcePackManager, Consumer applier, CallbackInfo ci) { - this.enabledPacks.removeIf(profile -> ((FabricResourcePackProfile) profile).isHidden()); - this.disabledPacks.removeIf(profile -> ((FabricResourcePackProfile) profile).isHidden()); + this.enabledPacks.removeIf(profile -> ((FabricResourcePackProfile) profile).fabric_isHidden()); + this.disabledPacks.removeIf(profile -> ((FabricResourcePackProfile) profile).fabric_isHidden()); } @Inject(method = "refresh", at = @At("TAIL")) private void removeHiddenPacksRefresh(CallbackInfo ci) { - this.enabledPacks.removeIf(profile -> ((FabricResourcePackProfile) profile).isHidden()); - this.disabledPacks.removeIf(profile -> ((FabricResourcePackProfile) profile).isHidden()); + this.enabledPacks.removeIf(profile -> ((FabricResourcePackProfile) profile).fabric_isHidden()); + this.disabledPacks.removeIf(profile -> ((FabricResourcePackProfile) profile).fabric_isHidden()); } } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java index e419ca2fbf..5f9d9873c7 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/FabricResourcePackProfile.java @@ -27,7 +27,7 @@ public interface FabricResourcePackProfile { /** * Returns whether the pack is internal and hidden from end users. */ - default boolean isHidden() { + default boolean fabric_isHidden() { return false; } @@ -38,10 +38,10 @@ default boolean isHidden() { * * @return whether every parent is enabled. */ - default boolean parentsEnabled(Set enabled) { + default boolean fabric_parentsEnabled(Set enabled) { return true; } - default void setParentsPredicate(Predicate> predicate) { + default void fabric_setParentsPredicate(Predicate> predicate) { } } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java index 3d6fefbfb6..ea3464c4d9 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackCreator.java @@ -132,7 +132,7 @@ private void registerModPack(Consumer consumer, @Nullable S ); if (profile != null) { - ((FabricResourcePackProfile) profile).setParentsPredicate(parents); + ((FabricResourcePackProfile) profile).fabric_setParentsPredicate(parents); consumer.accept(profile); } } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java index 71a0b56142..093b95d274 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModResourcePackUtil.java @@ -88,10 +88,9 @@ public static void appendModResourcePacks(List packs, ResourceT public static void refreshAutoEnabledPacks(List enabledProfiles, Map allProfiles) { LOGGER.debug("[Fabric] Starting internal pack sorting with: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); - enabledProfiles.removeIf(profile -> ((FabricResourcePackProfile) profile).isHidden()); + enabledProfiles.removeIf(profile -> ((FabricResourcePackProfile) profile).fabric_isHidden()); LOGGER.debug("[Fabric] Removed all internal packs, result: {}", enabledProfiles.stream().map(ResourcePackProfile::getName).toList()); ListIterator it = enabledProfiles.listIterator(); - // LinkedHashSet for debug log sort, will switch to normal HashSet once finished Set seen = new LinkedHashSet<>(); while (it.hasNext()) { @@ -101,7 +100,7 @@ public static void refreshAutoEnabledPacks(List enabledProf for (ResourcePackProfile p : allProfiles.values()) { FabricResourcePackProfile fp = (FabricResourcePackProfile) p; - if (fp.isHidden() && fp.parentsEnabled(seen) && seen.add(p.getName())) { + if (fp.fabric_isHidden() && fp.fabric_parentsEnabled(seen) && seen.add(p.getName())) { it.add(p); LOGGER.debug("[Fabric] cur @ {}, auto-enabled {}, currently enabled: {}", profile.getName(), p.getName(), seen); } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java index 53191c806a..8d2338b1f4 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DatapackCommandMixin.java @@ -53,16 +53,16 @@ public class DatapackCommandMixin { @Redirect(method = "method_13136", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourcePackManager;getEnabledNames()Ljava/util/Collection;")) private static Collection filterEnabledPackSuggestions(ResourcePackManager dataPackManager) { - return dataPackManager.getEnabledProfiles().stream().filter(profile -> !((FabricResourcePackProfile) profile).isHidden()).map(ResourcePackProfile::getName).toList(); + return dataPackManager.getEnabledProfiles().stream().filter(profile -> !((FabricResourcePackProfile) profile).fabric_isHidden()).map(ResourcePackProfile::getName).toList(); } @WrapOperation(method = "method_13120", at = @At(value = "INVOKE", target = "Ljava/util/stream/Stream;filter(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;", ordinal = 0)) private static Stream filterDisabledPackSuggestions(Stream instance, Predicate predicate, Operation> original) { - return original.call(instance, predicate).filter(profile -> !((FabricResourcePackProfile) profile).isHidden()); + return original.call(instance, predicate).filter(profile -> !((FabricResourcePackProfile) profile).fabric_isHidden()); } @Inject(method = "getPackContainer", at = @At(value = "INVOKE", target = "Ljava/util/Collection;contains(Ljava/lang/Object;)Z", shift = At.Shift.BEFORE)) private static void errorOnInternalPack(CommandContext context, String name, boolean enable, CallbackInfoReturnable cir, @Local ResourcePackProfile profile) throws CommandSyntaxException { - if (((FabricResourcePackProfile) profile).isHidden()) throw INTERNAL_PACK_EXCEPTION.create(profile.getName()); + if (((FabricResourcePackProfile) profile).fabric_isHidden()) throw INTERNAL_PACK_EXCEPTION.create(profile.getName()); } } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java index a1ec184366..bfa3157006 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackManagerMixin.java @@ -99,7 +99,7 @@ private void handleAutoEnable(String profile, CallbackInfoReturnable ci private void handleAutoDisable(String profile, CallbackInfoReturnable cir, @Local List enabled) { if (ModResourcePackCreator.POST_CHANGE_HANDLE_REQUIRED.contains(profile)) { Set currentlyEnabled = enabled.stream().map(ResourcePackProfile::getName).collect(Collectors.toSet()); - enabled.removeIf(p -> !((FabricResourcePackProfile) p).parentsEnabled(currentlyEnabled)); + enabled.removeIf(p -> !((FabricResourcePackProfile) p).fabric_parentsEnabled(currentlyEnabled)); LOGGER.debug("[Fabric] Internal pack auto-removed upon disabling {}, result: {}", profile, enabled.stream().map(ResourcePackProfile::getName).toList()); } } diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackProfileMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackProfileMixin.java index e3e35e3171..a9c2ffec73 100644 --- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackProfileMixin.java +++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/ResourcePackProfileMixin.java @@ -57,17 +57,17 @@ private void onCreateResourcePack(CallbackInfoReturnable info) { } @Override - public boolean isHidden() { + public boolean fabric_isHidden() { return parentsPredicate != DEFAULT_PARENT_PREDICATE; } @Override - public boolean parentsEnabled(Set enabled) { + public boolean fabric_parentsEnabled(Set enabled) { return parentsPredicate.test(enabled); } @Override - public void setParentsPredicate(Predicate> predicate) { + public void fabric_setParentsPredicate(Predicate> predicate) { this.parentsPredicate = predicate; } } diff --git a/fabric-resource-loader-v0/src/test/java/net/fabricmc/fabric/test/resource/loader/unit/ModResourcePackUtilTests.java b/fabric-resource-loader-v0/src/test/java/net/fabricmc/fabric/test/resource/loader/unit/ModResourcePackUtilTests.java index 3cc04b5fe5..8921f275cf 100644 --- a/fabric-resource-loader-v0/src/test/java/net/fabricmc/fabric/test/resource/loader/unit/ModResourcePackUtilTests.java +++ b/fabric-resource-loader-v0/src/test/java/net/fabricmc/fabric/test/resource/loader/unit/ModResourcePackUtilTests.java @@ -214,7 +214,7 @@ private ResourcePackProfile mockProfile(Map profile ModResourcePackCreator.RESOURCE_PACK_SOURCE ); - if (parents != null) ((FabricResourcePackProfile) profile).setParentsPredicate(parents); + if (parents != null) ((FabricResourcePackProfile) profile).fabric_setParentsPredicate(parents); profiles.put(id, profile); return profile; From 150d210b40b8ff83aeb5f55b638eeb2833580a4b Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Thu, 18 Jan 2024 14:10:46 +0900 Subject: [PATCH 23/23] Update ja_jp.json --- .../resources/assets/fabric-resource-loader-v0/lang/ja_jp.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/ja_jp.json b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/ja_jp.json index 7d57b4def8..1bd4a28edf 100644 --- a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/ja_jp.json +++ b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/ja_jp.json @@ -1,5 +1,6 @@ { "pack.source.fabricmod": "Fabric mod", "pack.source.builtinMod": "ビルトイン: %s", - "pack.name.fabricMods": "Fabric Mod" + "pack.name.fabricMods": "Fabric Mod", + "commands.datapack.fabric.internal": "「%s」はFabric内部で管理されているため、有効化・無効化できません" }