From 68296ad5e51207d36cbed08ef3063097a27f838a Mon Sep 17 00:00:00 2001
From: Julian Burner <48808497+NebelNidas@users.noreply.github.com>
Date: Wed, 15 Mar 2023 13:00:49 +0100
Subject: [PATCH] Restore Programmer Art injection support (1.19.3) (#2957)

* Restore Programmer Art resource pack injection support

* Add Programmer Art injection testmod

* Fix license formatting

* Remove unnecessary `@Environment` annotation
---
 .../loader/ProgrammerArtResourcePack.java     |  98 ++++++++++++++++++
 ...efaultClientResourcePackProviderMixin.java |  65 ++++++++++++
 ...bric-resource-loader-v0.client.mixins.json |   1 +
 .../resource/loader/GroupResourcePack.java    |   8 +-
 .../loader/ModResourcePackCreator.java        |   5 +-
 .../resource/loader/ModResourcePackUtil.java  |   2 +-
 ...laBuiltinResourcePackInjectionTestMod.java |  42 ++++++++
 .../blockstates/testblock.json                |   7 ++
 .../models/block/testblock.json               |   6 ++
 .../models/item/testblock.json                |   3 +
 .../textures/block/testblock.png              | Bin 0 -> 5057 bytes
 .../src/testmod/resources/fabric.mod.json     |   3 +-
 .../textures/block/testblock.png              | Bin 0 -> 5030 bytes
 13 files changed, 233 insertions(+), 7 deletions(-)
 create mode 100644 fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/ProgrammerArtResourcePack.java
 create mode 100644 fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/DefaultClientResourcePackProviderMixin.java
 create mode 100644 fabric-resource-loader-v0/src/testmod/java/net/fabricmc/fabric/test/resource/loader/VanillaBuiltinResourcePackInjectionTestMod.java
 create mode 100644 fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/blockstates/testblock.json
 create mode 100644 fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/models/block/testblock.json
 create mode 100644 fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/models/item/testblock.json
 create mode 100644 fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/textures/block/testblock.png
 create mode 100644 fabric-resource-loader-v0/src/testmod/resources/programmer_art/assets/fabric-resource-loader-v0-testmod/textures/block/testblock.png

diff --git a/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/ProgrammerArtResourcePack.java b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/ProgrammerArtResourcePack.java
new file mode 100644
index 000000000..556c93acb
--- /dev/null
+++ b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/impl/client/resource/loader/ProgrammerArtResourcePack.java
@@ -0,0 +1,98 @@
+/*
+ * 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.Set;
+
+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.minecraft.util.Identifier;
+import net.minecraft.util.PathUtil;
+
+import net.fabricmc.fabric.api.resource.ModResourcePack;
+import net.fabricmc.fabric.impl.resource.loader.GroupResourcePack;
+
+/**
+ * Represents the Programmer Art resource pack with support for modded content.
+ *
+ * <p>Any vanilla resources are provided like in Vanilla through the original programmer art, any missing resources
+ * will be searched in the provided modded resource packs.
+ */
+public class ProgrammerArtResourcePack extends GroupResourcePack {
+	private final AbstractFileResourcePack originalResourcePack;
+
+	public ProgrammerArtResourcePack(AbstractFileResourcePack originalResourcePack, List<ModResourcePack> modResourcePacks) {
+		super(ResourceType.CLIENT_RESOURCES, modResourcePacks);
+		this.originalResourcePack = originalResourcePack;
+	}
+
+	@Override
+	public InputSupplier<InputStream> openRoot(String... pathSegments) {
+		PathUtil.validatePath(pathSegments);
+
+		return this.originalResourcePack.openRoot(String.join("/", pathSegments));
+	}
+
+	@Override
+	public InputSupplier<InputStream> open(ResourceType type, Identifier id) {
+		InputSupplier<InputStream> originalPackData = this.originalResourcePack.open(type, id);
+
+		if (originalPackData != null) {
+			return originalPackData;
+		}
+
+		return super.open(type, id);
+	}
+
+	@Override
+	public void findResources(ResourceType type, String namespace, String prefix, ResultConsumer consumer) {
+		super.findResources(type, namespace, prefix, consumer);
+		this.originalResourcePack.findResources(type, namespace, prefix, consumer);
+	}
+
+	@Override
+	public Set<String> getNamespaces(ResourceType type) {
+		Set<String> namespaces = this.originalResourcePack.getNamespaces(type);
+
+		namespaces.addAll(super.getNamespaces(type));
+
+		return namespaces;
+	}
+
+	@Override
+	public <T> @Nullable T parseMetadata(ResourceMetadataReader<T> metaReader) throws IOException {
+		return this.originalResourcePack.parseMetadata(metaReader);
+	}
+
+	@Override
+	public String getName() {
+		return "Programmer Art";
+	}
+
+	@Override
+	public void close() {
+		this.originalResourcePack.close();
+		super.close();
+	}
+}
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
new file mode 100644
index 000000000..4c839a327
--- /dev/null
+++ b/fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client/DefaultClientResourcePackProviderMixin.java
@@ -0,0 +1,65 @@
+/*
+ * 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.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.ProgrammerArtResourcePack;
+import net.fabricmc.fabric.impl.resource.loader.ModResourcePackUtil;
+
+@Mixin(DefaultClientResourcePackProvider.class)
+public class DefaultClientResourcePackProviderMixin {
+	/**
+	 * Injects into the method which registers/creates the Programmer Art resource pack,
+	 * and replaces the local {@link net.minecraft.resource.ResourcePackProfile.PackFactory}
+	 * instance with our custom Programmer Art 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 onCreateProgrammerArtResourcePack(String name, Text displayName, boolean alwaysEnabled,
+			ResourcePackProfile.PackFactory packFactory, ResourceType type, ResourcePackProfile.InsertionPosition position, ResourcePackSource source) {
+		return factory -> new ProgrammerArtResourcePack((AbstractFileResourcePack) packFactory.open(name), getProgrammerArtModResourcePacks());
+	}
+
+	/**
+	 * {@return} all baked-in mod resource packs that provide Programmer Art resources.
+	 */
+	private static List<ModResourcePack> getProgrammerArtModResourcePacks() {
+		List<ModResourcePack> packs = new ArrayList<>();
+		ModResourcePackUtil.appendModResourcePacks(packs, ResourceType.CLIENT_RESOURCES, "programmer_art");
+		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 147c842d3..90f7c7622 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,6 +4,7 @@
   "compatibilityLevel": "JAVA_16",
   "client": [
     "VanillaResourcePackProviderMixin",
+    "DefaultClientResourcePackProviderMixin",
     "CreateWorldScreenMixin",
     "FontManagerMixin",
     "GameOptionsMixin",
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
index 6ee2708f3..5fb752a99 100644
--- 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
@@ -70,13 +70,17 @@ public abstract class GroupResourcePack implements ResourcePack {
 	}
 
 	@Override
-	public void findResources(ResourceType type, String namespace, String prefix, ResultConsumer arg) {
+	public void findResources(ResourceType type, String namespace, String prefix, ResultConsumer consumer) {
 		List<ModResourcePack> packs = this.namespacedPacks.get(namespace);
 
+		if (packs == null) {
+			return;
+		}
+
 		for (int i = packs.size() - 1; i >= 0; i--) {
 			ResourcePack pack = packs.get(i);
 
-			pack.findResources(type, namespace, prefix, arg);
+			pack.findResources(type, namespace, prefix, consumer);
 		}
 	}
 
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 b45511567..d1380ed45 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
@@ -76,9 +76,8 @@ public class ModResourcePackCreator implements ResourcePackProvider {
 
 		if (!packs.isEmpty()) {
 			// Make the resource pack profile for mod resource packs.
-			// Mod resource packs must always be enabled to avoid issues
-			// and inserted on top to ensure that they are applied before user resource packs and after default/programmer art resource pack.
-			// @TODO: "inserted on top" comment is deprecated, it does not guarantee the condition "applied before user 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, factory -> new FabricModResourcePack(this.type, packs), type, ResourcePackProfile.InsertionPosition.TOP,
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 3a4dc60b1..505a2461a 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
@@ -68,7 +68,7 @@ public final class ModResourcePackUtil {
 				continue;
 			}
 
-			ModResourcePack pack = ModNioResourcePack.create(new Identifier("fabric", container.getMetadata().getId()), getName(container.getMetadata()), container, null, type, ResourcePackActivationType.ALWAYS_ENABLED);
+			ModResourcePack pack = ModNioResourcePack.create(new Identifier("fabric", container.getMetadata().getId()), getName(container.getMetadata()), container, subPath, type, ResourcePackActivationType.ALWAYS_ENABLED);
 
 			if (pack != null) {
 				packs.add(pack);
diff --git a/fabric-resource-loader-v0/src/testmod/java/net/fabricmc/fabric/test/resource/loader/VanillaBuiltinResourcePackInjectionTestMod.java b/fabric-resource-loader-v0/src/testmod/java/net/fabricmc/fabric/test/resource/loader/VanillaBuiltinResourcePackInjectionTestMod.java
new file mode 100644
index 000000000..97c26d584
--- /dev/null
+++ b/fabric-resource-loader-v0/src/testmod/java/net/fabricmc/fabric/test/resource/loader/VanillaBuiltinResourcePackInjectionTestMod.java
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+import net.minecraft.block.AbstractBlock;
+import net.minecraft.block.Block;
+import net.minecraft.block.Blocks;
+import net.minecraft.item.BlockItem;
+import net.minecraft.item.Item;
+import net.minecraft.registry.Registries;
+import net.minecraft.registry.Registry;
+import net.minecraft.util.Identifier;
+
+import net.fabricmc.api.ModInitializer;
+
+public class VanillaBuiltinResourcePackInjectionTestMod implements ModInitializer {
+	public static final String MODID = "fabric-resource-loader-v0-testmod";
+
+	public static final Block TEST_BLOCK = new Block(AbstractBlock.Settings.copy(Blocks.STONE));
+
+	@Override
+	public void onInitialize() {
+		Identifier id = new Identifier(MODID, "testblock");
+
+		Registry.register(Registries.BLOCK, id, TEST_BLOCK);
+		Registry.register(Registries.ITEM, id, new BlockItem(TEST_BLOCK, new Item.Settings()));
+	}
+}
diff --git a/fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/blockstates/testblock.json b/fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/blockstates/testblock.json
new file mode 100644
index 000000000..240a5c536
--- /dev/null
+++ b/fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/blockstates/testblock.json
@@ -0,0 +1,7 @@
+{
+  "variants": {
+    "": {
+      "model": "fabric-resource-loader-v0-testmod:block/testblock"
+    }
+  }
+}
diff --git a/fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/models/block/testblock.json b/fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/models/block/testblock.json
new file mode 100644
index 000000000..9724f111f
--- /dev/null
+++ b/fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/models/block/testblock.json
@@ -0,0 +1,6 @@
+{
+  "parent": "block/cube_all",
+  "textures": {
+    "all": "fabric-resource-loader-v0-testmod:block/testblock"
+  }
+}
diff --git a/fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/models/item/testblock.json b/fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/models/item/testblock.json
new file mode 100644
index 000000000..401cdd258
--- /dev/null
+++ b/fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/models/item/testblock.json
@@ -0,0 +1,3 @@
+{
+  "parent": "fabric-resource-loader-v0-testmod:block/testblock"
+}
diff --git a/fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/textures/block/testblock.png b/fabric-resource-loader-v0/src/testmod/resources/assets/fabric-resource-loader-v0-testmod/textures/block/testblock.png
new file mode 100644
index 0000000000000000000000000000000000000000..654fd938e9e9590e4f1d6b67ef0b2687e8142e29
GIT binary patch
literal 5057
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
S|0eK(6dVxdzkk_>+5Z9i^^4X3

literal 0
HcmV?d00001

diff --git a/fabric-resource-loader-v0/src/testmod/resources/fabric.mod.json b/fabric-resource-loader-v0/src/testmod/resources/fabric.mod.json
index 659a391f8..3739e7234 100644
--- a/fabric-resource-loader-v0/src/testmod/resources/fabric.mod.json
+++ b/fabric-resource-loader-v0/src/testmod/resources/fabric.mod.json
@@ -11,7 +11,8 @@
   "entrypoints": {
     "main": [
       "net.fabricmc.fabric.test.resource.loader.BuiltinResourcePackTestMod",
-      "net.fabricmc.fabric.test.resource.loader.ResourceReloadListenerTestMod"
+      "net.fabricmc.fabric.test.resource.loader.ResourceReloadListenerTestMod",
+      "net.fabricmc.fabric.test.resource.loader.VanillaBuiltinResourcePackInjectionTestMod"
     ],
     "server": [
       "net.fabricmc.fabric.test.resource.loader.LanguageTestMod"
diff --git a/fabric-resource-loader-v0/src/testmod/resources/programmer_art/assets/fabric-resource-loader-v0-testmod/textures/block/testblock.png b/fabric-resource-loader-v0/src/testmod/resources/programmer_art/assets/fabric-resource-loader-v0-testmod/textures/block/testblock.png
new file mode 100644
index 0000000000000000000000000000000000000000..fef4498f10c455e46664314a39d25cf12b659448
GIT binary patch
literal 5030
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

literal 0
HcmV?d00001