From 6960386503719512367874ef082a6473dbcadc49 Mon Sep 17 00:00:00 2001 From: Blodhgarm Date: Sat, 20 Jul 2024 15:19:26 -0500 Subject: [PATCH] [1.20.1 - Fabric] Adjust logic for equipping hats to tag method using tag injection (#77) * Switch to using tag injector method for adding hats to hat slot for trinkets rather than a mixin into trinkets * Adjust code for render Armor to use `getEquipped` instead * Update modmenu to prevent issues with running game in dev --- gradle.properties | 2 +- .../fonnymunkey/simplehats/SimpleHats.java | 4 + .../simplehats/common/init/ModRegistry.java | 3 + .../mixin/core/MixinHumanoidArmorLayer.java | 10 +- .../mixin/core/MixinTagGroupLoader.java | 40 ++++++ .../mixin/core/MixinTrinketsApi.java | 25 ---- .../simplehats/util/TagInjector.java | 124 ++++++++++++++++++ .../data/simplehats/tags/items/all_hats.json | 4 + .../data/trinkets/tags/items/head/hat.json | 6 + src/main/resources/mixins.simplehats.json | 2 +- 10 files changed, 188 insertions(+), 32 deletions(-) create mode 100644 src/main/java/fonnymunkey/simplehats/mixin/core/MixinTagGroupLoader.java delete mode 100644 src/main/java/fonnymunkey/simplehats/mixin/core/MixinTrinketsApi.java create mode 100644 src/main/java/fonnymunkey/simplehats/util/TagInjector.java create mode 100644 src/main/resources/data/simplehats/tags/items/all_hats.json create mode 100644 src/main/resources/data/trinkets/tags/items/head/hat.json diff --git a/gradle.properties b/gradle.properties index ee22f69..f1f32ba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,4 +18,4 @@ org.gradle.daemon=false trinkets_version=3.7.0 cloth_config_version=11.0.99 cc_version=5.2.0 - modmenu_version=5.0.2 \ No newline at end of file + modmenu_version=7.2.2 \ No newline at end of file diff --git a/src/main/java/fonnymunkey/simplehats/SimpleHats.java b/src/main/java/fonnymunkey/simplehats/SimpleHats.java index e827883..7b9f917 100644 --- a/src/main/java/fonnymunkey/simplehats/SimpleHats.java +++ b/src/main/java/fonnymunkey/simplehats/SimpleHats.java @@ -13,6 +13,7 @@ import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; import net.fabricmc.fabric.api.loot.v2.LootTableEvents; import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry; +import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; import net.minecraft.loot.LootPool; @@ -24,6 +25,7 @@ import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.tag.TagKey; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import org.apache.logging.log4j.LogManager; @@ -36,6 +38,8 @@ public class SimpleHats implements ModInitializer { public static RegistryKey HAT_TAB = RegistryKey.of(RegistryKeys.ITEM_GROUP, new Identifier(modId, "hat_group")); + public static final TagKey ALL_HATS = TagKey.of(RegistryKeys.ITEM, new Identifier(modId, "all_hats")); + @Override public void onInitialize() { config = AutoConfig.register(ModConfig.class, PartitioningSerializer.wrap(Toml4jConfigSerializer::new)).getConfig(); diff --git a/src/main/java/fonnymunkey/simplehats/common/init/ModRegistry.java b/src/main/java/fonnymunkey/simplehats/common/init/ModRegistry.java index 0f2d573..91a1f21 100644 --- a/src/main/java/fonnymunkey/simplehats/common/init/ModRegistry.java +++ b/src/main/java/fonnymunkey/simplehats/common/init/ModRegistry.java @@ -10,6 +10,7 @@ import fonnymunkey.simplehats.common.recipe.HatVariantRecipe; import fonnymunkey.simplehats.util.HatEntry; import fonnymunkey.simplehats.util.HatEntry.HatSeason; +import fonnymunkey.simplehats.util.TagInjector; import net.minecraft.block.cauldron.CauldronBehavior; import net.minecraft.entity.EntityType; import net.minecraft.entity.SpawnGroup; @@ -62,6 +63,8 @@ public static void registerHats() { if(hat instanceof HatItemDyeable) CauldronBehavior.WATER_CAULDRON_BEHAVIOR.put((HatItemDyeable)hat, CauldronBehavior.CLEAN_DYEABLE_ITEM); } SimpleHats.logger.log(Level.INFO, "Generated " + ModRegistry.hatList.size() + " hat items from hat entries."); + + TagInjector.inject(Registries.ITEM, SimpleHats.ALL_HATS.id(), ModRegistry.hatList.stream().map(hatItem -> (Item) hatItem).toList()); } //// diff --git a/src/main/java/fonnymunkey/simplehats/mixin/core/MixinHumanoidArmorLayer.java b/src/main/java/fonnymunkey/simplehats/mixin/core/MixinHumanoidArmorLayer.java index 614994a..009f04f 100644 --- a/src/main/java/fonnymunkey/simplehats/mixin/core/MixinHumanoidArmorLayer.java +++ b/src/main/java/fonnymunkey/simplehats/mixin/core/MixinHumanoidArmorLayer.java @@ -20,11 +20,11 @@ public class MixinHumanoidArmorLayer { @Inject(method = "renderArmor", at = @At("HEAD"), cancellable = true) public void simplehats_renderArmor(MatrixStack matrices, VertexConsumerProvider vertexConsumers, LivingEntity entity, EquipmentSlot armorSlot, int light, BipedEntityModel model, CallbackInfo ci) { if(entity instanceof PlayerEntity && armorSlot.equals(EquipmentSlot.HEAD)) { - TrinketsApi.getTrinketComponent(entity).ifPresent(component -> - component.forEach((slotReference, stack) -> { - if(stack.getItem() instanceof HatItem) ci.cancel(); - }) - ); + TrinketsApi.getTrinketComponent(entity).ifPresent(component -> { + var hasHatTrinket = !component.getEquipped(stack -> stack.getItem() instanceof HatItem).isEmpty(); + + if(hasHatTrinket) ci.cancel(); + }); } } } diff --git a/src/main/java/fonnymunkey/simplehats/mixin/core/MixinTagGroupLoader.java b/src/main/java/fonnymunkey/simplehats/mixin/core/MixinTagGroupLoader.java new file mode 100644 index 0000000..df96f16 --- /dev/null +++ b/src/main/java/fonnymunkey/simplehats/mixin/core/MixinTagGroupLoader.java @@ -0,0 +1,40 @@ +package fonnymunkey.simplehats.mixin.core; + +import fonnymunkey.simplehats.util.TagInjector; +import net.minecraft.registry.tag.TagGroupLoader; +import net.minecraft.resource.ResourceManager; +import net.minecraft.util.Identifier; +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.CallbackInfoReturnable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Code taken 1:1 from TagGroupLoaderMixin + *

+ * Such is under the MIT license and full credits go to glisco for such + */ +@Mixin(TagGroupLoader.class) +public class MixinTagGroupLoader { + @Shadow + @Final + private String dataType; + + @Inject(method = "loadTags", at = @At("TAIL")) + public void injectValues(ResourceManager manager, CallbackInfoReturnable>> cir) { + var map = cir.getReturnValue(); + + TagInjector.ADDITIONS.forEach((location, entries) -> { + if (!this.dataType.equals(location.type())) return; + + var list = map.computeIfAbsent(location.tagId(), id -> new ArrayList<>()); + entries.forEach(addition -> list.add(new TagGroupLoader.TrackedEntry(addition, "owo"))); + }); + } +} \ No newline at end of file diff --git a/src/main/java/fonnymunkey/simplehats/mixin/core/MixinTrinketsApi.java b/src/main/java/fonnymunkey/simplehats/mixin/core/MixinTrinketsApi.java deleted file mode 100644 index 27224c1..0000000 --- a/src/main/java/fonnymunkey/simplehats/mixin/core/MixinTrinketsApi.java +++ /dev/null @@ -1,25 +0,0 @@ -package fonnymunkey.simplehats.mixin.core; - -import dev.emi.trinkets.api.SlotReference; -import dev.emi.trinkets.api.TrinketsApi; -import fonnymunkey.simplehats.common.item.HatItem; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -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 java.util.Set; - -@Mixin(TrinketsApi.class) -public class MixinTrinketsApi { - - @Inject(method = "evaluatePredicateSet", at = @At("RETURN"), remap = false, cancellable = true) - private static void simplehats_evaluatePredicateSet(Set set, ItemStack stack, SlotReference ref, LivingEntity entity, CallbackInfoReturnable cir) { - if(stack.getItem() instanceof HatItem && ref.inventory().getSlotType().getName().equalsIgnoreCase("hat")) { - cir.setReturnValue(true); - } - } -} \ No newline at end of file diff --git a/src/main/java/fonnymunkey/simplehats/util/TagInjector.java b/src/main/java/fonnymunkey/simplehats/util/TagInjector.java new file mode 100644 index 0000000..77f7d8f --- /dev/null +++ b/src/main/java/fonnymunkey/simplehats/util/TagInjector.java @@ -0,0 +1,124 @@ +package fonnymunkey.simplehats.util; + +import com.google.common.collect.ForwardingMap; +import net.minecraft.registry.Registry; +import net.minecraft.registry.tag.TagEntry; +import net.minecraft.registry.tag.TagManagerLoader; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.function.Function; + +/** + * Code taken 1:1 from TagInjector + *

+ * Such is under the MIT license and full credits go to glisco for such + */ +public final class TagInjector { + @ApiStatus.Internal + public static final HashMap> ADDITIONS = new HashMap<>(); + + private static final Map> ADDITIONS_VIEW = new ForwardingMap<>() { + @Override + protected @NotNull Map> delegate() { + return Collections.unmodifiableMap(ADDITIONS); + } + + @Override + public Set get(@Nullable Object key) { + return Collections.unmodifiableSet(this.delegate().get(key)); + } + }; + + private TagInjector() {} + + /** + * @return A view of all planned tag injections + */ + public static Map> getInjections() { + return ADDITIONS_VIEW; + } + + /** + * Inject the given identifiers into the given tag + *

+ * If any of the identifiers don't correspond to an entry in the + * given registry, you will break the tag. + * If the tag does not exist, it will be created. + * + * @param registry The registry for which the injected tags should apply + * @param tag The tag to insert into, this could contain all kinds of values + * @param entryMaker The function to use for creating tag entries from the given identifiers + * @param values The values to insert + */ + public static void injectRaw(Registry registry, Identifier tag, Function entryMaker, Collection values) { + ADDITIONS.computeIfAbsent(new TagLocation(TagManagerLoader.getPath(registry.getKey()), tag), identifier -> new HashSet<>()) + .addAll(values.stream().map(entryMaker).toList()); + } + + public static void injectRaw(Registry registry, Identifier tag, Function entryMaker, Identifier... values) { + injectRaw(registry, tag, entryMaker, Arrays.asList(values)); + } + + // ------- + + /** + * Inject the given values into the given tag, obtaining + * their identifiers from the given registry + * + * @param registry The registry the target tag is for + * @param tag The identifier of the tag to inject into + * @param values The values to inject + * @param The type of the target registry + */ + public static void inject(Registry registry, Identifier tag, Collection values) { + injectDirectReference(registry, tag, values.stream().map(registry::getId).toList()); + } + + @SafeVarargs + public static void inject(Registry registry, Identifier tag, T... values) { + inject(registry, tag, Arrays.asList(values)); + } + + // ------- + + /** + * Inject the given identifiers into the given tag + * + * @param registry The registry the target tag is for + * @param tag The identifier of the tag to inject into + * @param values The values to inject + */ + public static void injectDirectReference(Registry registry, Identifier tag, Collection values) { + injectRaw(registry, tag, TagEntry::create, values); + } + + public static void injectDirectReference(Registry registry, Identifier tag, Identifier... values) { + injectDirectReference(registry, tag, Arrays.asList(values)); + } + + // ------- + + /** + * Inject the given tags into the given tag, + * effectively nesting them. This is equivalent to + * prefixing an entry in the tag JSON's {@code values} array + * with a {@code #} + * + * @param registry The registry the target tag is for + * @param tag The identifier of the tag to inject into + * @param values The values to inject + */ + public static void injectTagReference(Registry registry, Identifier tag, Collection values) { + injectRaw(registry, tag, TagEntry::createTag, values); + } + + public static void injectTagReference(Registry registry, Identifier tag, Identifier... values) { + injectTagReference(registry, tag, Arrays.asList(values)); + } + + public record TagLocation(String type, Identifier tagId) {} +} \ No newline at end of file diff --git a/src/main/resources/data/simplehats/tags/items/all_hats.json b/src/main/resources/data/simplehats/tags/items/all_hats.json new file mode 100644 index 0000000..5e8aecc --- /dev/null +++ b/src/main/resources/data/simplehats/tags/items/all_hats.json @@ -0,0 +1,4 @@ +{ + "replace": false, + "values": [] +} \ No newline at end of file diff --git a/src/main/resources/data/trinkets/tags/items/head/hat.json b/src/main/resources/data/trinkets/tags/items/head/hat.json new file mode 100644 index 0000000..ff7589e --- /dev/null +++ b/src/main/resources/data/trinkets/tags/items/head/hat.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "#simplehats:all_hats" + ] +} \ No newline at end of file diff --git a/src/main/resources/mixins.simplehats.json b/src/main/resources/mixins.simplehats.json index 8827e2d..e3a72f2 100644 --- a/src/main/resources/mixins.simplehats.json +++ b/src/main/resources/mixins.simplehats.json @@ -5,7 +5,7 @@ "refmap": "simplehats-fabric-refmap.json", "mixins": [ "MixinLivingEntity", - "MixinTrinketsApi" + "MixinTagGroupLoader" ], "minVersion": "0.8", "client": [