From 93d0538f35b32ecff0eeb8e17fc4a682e0e6c38a Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sun, 23 Oct 2022 19:24:39 +0800 Subject: [PATCH] Add Item.Properties().arch$tab(CreativeModeTab) --- build.gradle | 4 - .../InjectedItemPropertiesExtension.java | 31 ++++++++ .../impl/ItemPropertiesExtensionImpl.java | 30 ++++++++ .../architectury/mixin/inject/MixinItem.java | 13 ++++ .../mixin/inject/MixinItemProperties.java | 46 ++++++++++++ .../registry/CreativeTabRegistry.java | 64 ++++++++++++++++ .../resources/architectury-common.mixins.json | 1 + .../main/resources/architectury.common.json | 3 + .../fabric/CreativeTabRegistryImpl.java | 73 ++++++++++++++++++- gradle.properties | 2 +- .../test/registry/TestRegistries.java | 16 ++-- .../test/tab/TestCreativeTabs.java | 11 +-- .../main/resources/architectury.common.json | 31 ++++++++ 13 files changed, 300 insertions(+), 25 deletions(-) create mode 100644 common/src/main/java/dev/architectury/extensions/injected/InjectedItemPropertiesExtension.java create mode 100644 common/src/main/java/dev/architectury/impl/ItemPropertiesExtensionImpl.java create mode 100644 common/src/main/java/dev/architectury/mixin/inject/MixinItemProperties.java create mode 100644 testmod-common/src/main/resources/architectury.common.json diff --git a/build.gradle b/build.gradle index fb24fd77..c9ceabb5 100644 --- a/build.gradle +++ b/build.gradle @@ -27,10 +27,6 @@ subprojects { silentMojangMappingsLicense() } - repositories { - mavenLocal() - } - dependencies { minecraft "com.mojang:minecraft:${rootProject.architectury.minecraft}" mappings loom.officialMojangMappings() diff --git a/common/src/main/java/dev/architectury/extensions/injected/InjectedItemPropertiesExtension.java b/common/src/main/java/dev/architectury/extensions/injected/InjectedItemPropertiesExtension.java new file mode 100644 index 00000000..2e3169ab --- /dev/null +++ b/common/src/main/java/dev/architectury/extensions/injected/InjectedItemPropertiesExtension.java @@ -0,0 +1,31 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.extensions.injected; + +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.Item; +import org.jetbrains.annotations.ApiStatus; + +public interface InjectedItemPropertiesExtension { + @ApiStatus.Experimental + default Item.Properties arch$tab(CreativeModeTab tab) { + throw new UnsupportedOperationException(); + } +} diff --git a/common/src/main/java/dev/architectury/impl/ItemPropertiesExtensionImpl.java b/common/src/main/java/dev/architectury/impl/ItemPropertiesExtensionImpl.java new file mode 100644 index 00000000..458f6a87 --- /dev/null +++ b/common/src/main/java/dev/architectury/impl/ItemPropertiesExtensionImpl.java @@ -0,0 +1,30 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.impl; + +import net.minecraft.world.item.CreativeModeTab; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +@ApiStatus.Internal +public interface ItemPropertiesExtensionImpl { + @Nullable + CreativeModeTab arch$getTab(); +} diff --git a/common/src/main/java/dev/architectury/mixin/inject/MixinItem.java b/common/src/main/java/dev/architectury/mixin/inject/MixinItem.java index 4b2a34bc..6d8a3abe 100644 --- a/common/src/main/java/dev/architectury/mixin/inject/MixinItem.java +++ b/common/src/main/java/dev/architectury/mixin/inject/MixinItem.java @@ -20,9 +20,22 @@ package dev.architectury.mixin.inject; import dev.architectury.extensions.injected.InjectedItemExtension; +import dev.architectury.impl.ItemPropertiesExtensionImpl; +import dev.architectury.registry.CreativeTabRegistry; +import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.Item; 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; @Mixin(Item.class) public class MixinItem implements InjectedItemExtension { + @Inject(method = "", at = @At("RETURN")) + private void init(Item.Properties properties, CallbackInfo ci) { + CreativeModeTab tab = ((ItemPropertiesExtensionImpl) properties).arch$getTab(); + if (tab != null) { + CreativeTabRegistry.append(tab, (Item) (Object) this); + } + } } diff --git a/common/src/main/java/dev/architectury/mixin/inject/MixinItemProperties.java b/common/src/main/java/dev/architectury/mixin/inject/MixinItemProperties.java new file mode 100644 index 00000000..cde32a98 --- /dev/null +++ b/common/src/main/java/dev/architectury/mixin/inject/MixinItemProperties.java @@ -0,0 +1,46 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.mixin.inject; + +import dev.architectury.extensions.injected.InjectedItemPropertiesExtension; +import dev.architectury.impl.ItemPropertiesExtensionImpl; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.Item; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(Item.Properties.class) +public class MixinItemProperties implements InjectedItemPropertiesExtension, ItemPropertiesExtensionImpl { + @Unique + private CreativeModeTab tab; + + @Override + public Item.Properties arch$tab(CreativeModeTab tab) { + this.tab = tab; + return (Item.Properties) (Object) this; + } + + @Override + @Nullable + public CreativeModeTab arch$getTab() { + return tab; + } +} diff --git a/common/src/main/java/dev/architectury/registry/CreativeTabRegistry.java b/common/src/main/java/dev/architectury/registry/CreativeTabRegistry.java index 7a36598c..a96fe224 100644 --- a/common/src/main/java/dev/architectury/registry/CreativeTabRegistry.java +++ b/common/src/main/java/dev/architectury/registry/CreativeTabRegistry.java @@ -24,17 +24,81 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.ItemLike; +import org.jetbrains.annotations.ApiStatus; import java.util.function.BiConsumer; +import java.util.function.Consumer; import java.util.function.Supplier; public final class CreativeTabRegistry { private CreativeTabRegistry() { } + // I am sorry, fabric wants a resource location instead of the translation key for whatever reason + public static CreativeModeTab create(ResourceLocation name, Supplier icon) { + return create(name, icon, (flags, output) -> { + }); + } + // I am sorry, fabric wants a resource location instead of the translation key for whatever reason @ExpectPlatform + @ApiStatus.Experimental public static CreativeModeTab create(ResourceLocation name, Supplier icon, BiConsumer filler) { throw new AssertionError(); } + + @ExpectPlatform + @ApiStatus.Experimental + public static void modify(CreativeModeTab tab, Consumer filler) { + throw new AssertionError(); + } + + @ExpectPlatform + @ApiStatus.Experimental + public static void append(CreativeModeTab tab, ItemLike item) { + throw new AssertionError(); + } + + @ExpectPlatform + @ApiStatus.Experimental + public static void append(CreativeModeTab tab, ItemLike... items) { + throw new AssertionError(); + } + + @ExpectPlatform + @ApiStatus.Experimental + public static > void append(CreativeModeTab tab, T item) { + throw new AssertionError(); + } + + @ExpectPlatform + @ApiStatus.Experimental + public static > void append(CreativeModeTab tab, T... items) { + throw new AssertionError(); + } + + @ExpectPlatform + @ApiStatus.Experimental + public static void appendStack(CreativeModeTab tab, ItemStack item) { + throw new AssertionError(); + } + + @ExpectPlatform + @ApiStatus.Experimental + public static void appendStack(CreativeModeTab tab, ItemStack... items) { + throw new AssertionError(); + } + + @ExpectPlatform + @ApiStatus.Experimental + public static > void appendStack(CreativeModeTab tab, T item) { + throw new AssertionError(); + } + + @ExpectPlatform + @ApiStatus.Experimental + public static > void appendStack(CreativeModeTab tab, T... items) { + throw new AssertionError(); + } } diff --git a/common/src/main/resources/architectury-common.mixins.json b/common/src/main/resources/architectury-common.mixins.json index 76b27514..dbe32348 100644 --- a/common/src/main/resources/architectury-common.mixins.json +++ b/common/src/main/resources/architectury-common.mixins.json @@ -13,6 +13,7 @@ "inject.MixinFoodPropertiesBuilder", "inject.MixinGameEvent", "inject.MixinItem", + "inject.MixinItemProperties", "inject.MixinLiquidBlock", "MixinLightningBolt" ], diff --git a/common/src/main/resources/architectury.common.json b/common/src/main/resources/architectury.common.json index a6d0c93c..3b8c7968 100644 --- a/common/src/main/resources/architectury.common.json +++ b/common/src/main/resources/architectury.common.json @@ -4,6 +4,9 @@ "net/minecraft/class_1792": [ "dev/architectury/extensions/injected/InjectedItemExtension" ], + "net/minecraft/class_1792$class_1793": [ + "dev/architectury/extensions/injected/InjectedItemPropertiesExtension" + ], "net/minecraft/class_2248": [ "dev/architectury/extensions/injected/InjectedBlockExtension" ], diff --git a/fabric/src/main/java/dev/architectury/registry/fabric/CreativeTabRegistryImpl.java b/fabric/src/main/java/dev/architectury/registry/fabric/CreativeTabRegistryImpl.java index f9973eff..ca8fe563 100644 --- a/fabric/src/main/java/dev/architectury/registry/fabric/CreativeTabRegistryImpl.java +++ b/fabric/src/main/java/dev/architectury/registry/fabric/CreativeTabRegistryImpl.java @@ -19,17 +19,28 @@ package dev.architectury.registry.fabric; +import com.google.common.collect.Multimap; +import com.google.common.collect.MultimapBuilder; import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup; +import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.CreativeModeTab.Output; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.ItemLike; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.ApiStatus.Experimental; import java.util.function.BiConsumer; +import java.util.function.Consumer; import java.util.function.Supplier; public class CreativeTabRegistryImpl { - public static CreativeModeTab create(ResourceLocation name, Supplier icon, BiConsumer filler) { + private static final Multimap> APPENDS = MultimapBuilder.hashKeys().arrayListValues().build(); + + @ApiStatus.Experimental + public static CreativeModeTab create(ResourceLocation name, Supplier icon, BiConsumer filler) { return new FabricItemGroup(name) { @Override public ItemStack makeIcon() { @@ -37,9 +48,67 @@ public class CreativeTabRegistryImpl { } @Override - protected void generateDisplayItems(FeatureFlagSet flags, CreativeModeTab.Output output) { + protected void generateDisplayItems(FeatureFlagSet flags, Output output) { filler.accept(flags, output); } }; } + + static { + ItemGroupEvents.MODIFY_ENTRIES_ALL.register((tab, output) -> { + APPENDS.get(tab).forEach(s -> output.accept(s.get())); + }); + } + + public static void modify(CreativeModeTab tab, Consumer filler) { + ItemGroupEvents.modifyEntriesEvent(tab).register(filler::accept); + } + + @Experimental + public static void append(CreativeModeTab tab, ItemLike item) { + APPENDS.put(tab, () -> new ItemStack(item)); + } + + @Experimental + public static void append(CreativeModeTab tab, ItemLike... items) { + for (ItemLike item : items) { + append(tab, item); + } + } + + @Experimental + public static > void append(CreativeModeTab tab, T item) { + APPENDS.put(tab, () -> new ItemStack(item.get())); + } + + @Experimental + public static > void append(CreativeModeTab tab, T... items) { + for (T item : items) { + append(tab, item); + } + } + + @Experimental + public static void appendStack(CreativeModeTab tab, ItemStack item) { + APPENDS.put(tab, () -> item); + } + + @Experimental + public static void appendStack(CreativeModeTab tab, ItemStack... items) { + for (ItemStack item : items) { + appendStack(tab, item); + } + } + + @Experimental + public static > void appendStack(CreativeModeTab tab, T item) { + APPENDS.put(tab, (Supplier) item); + } + + @Experimental + public static > void appendStack(CreativeModeTab tab, T... items) { + for (T item : items) { + appendStack(tab, item); + } + } } diff --git a/gradle.properties b/gradle.properties index 19ae3294..6cac98ce 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,7 +15,7 @@ base_version=7.0 maven_group=dev.architectury fabric_loader_version=0.14.10 -fabric_api_version=0.64.0+local-mixinfix +fabric_api_version=0.65.0+1.19.3 mod_menu_version=3.1.0 forge_version=43.0.0 diff --git a/testmod-common/src/main/java/dev/architectury/test/registry/TestRegistries.java b/testmod-common/src/main/java/dev/architectury/test/registry/TestRegistries.java index 75322e63..acad4725 100644 --- a/testmod-common/src/main/java/dev/architectury/test/registry/TestRegistries.java +++ b/testmod-common/src/main/java/dev/architectury/test/registry/TestRegistries.java @@ -105,27 +105,27 @@ public class TestRegistries { }); public static final RegistrySupplier TEST_ITEM = ITEMS.register("test_item", () -> - new Item(new Item.Properties())); + new Item(new Item.Properties().arch$tab(TestCreativeTabs.TEST_TAB))); public static final RegistrySupplier TEST_EQUIPPABLE = ITEMS.register("test_eqippable", () -> - new EquippableTickingItem(new Item.Properties())); + new EquippableTickingItem(new Item.Properties().arch$tab(TestCreativeTabs.TEST_TAB))); public static final RegistrySupplier TEST_EDIBLE = ITEMS.register("test_edible", () -> { FoodProperties.Builder fpBuilder = new FoodProperties.Builder().nutrition(8).saturationMod(0.8F).meat(); FoodPropertiesHooks.effect(fpBuilder, () -> new MobEffectInstance(TEST_EFFECT.get(), 100), 1); - return new Item(new Item.Properties().food(fpBuilder.build())); + return new Item(new Item.Properties().food(fpBuilder.build()).arch$tab(TestCreativeTabs.TEST_TAB)); }); public static final RegistrySupplier TEST_SPAWN_EGG = ITEMS.register("test_spawn_egg", () -> new ArchitecturySpawnEggItem(TestRegistries.TEST_ENTITY, 0xFF000000, 0xFFFFFFFF, - new Item.Properties())); + new Item.Properties().arch$tab(TestCreativeTabs.TEST_TAB))); public static final RegistrySupplier TEST_SPAWN_EGG_2 = ITEMS.register("test_spawn_egg_2", () -> new ArchitecturySpawnEggItem(TestRegistries.TEST_ENTITY_2, 0xFFFFFFFF, 0xFF000000, - new Item.Properties())); + new Item.Properties().arch$tab(TestCreativeTabs.TEST_TAB))); public static final RegistrySupplier TEST_FLUID_BUCKET = ITEMS.register("test_fluid_bucket", () -> { try { // In example mod the forge class isn't being replaced, this is not required in mods depending on architectury return (Item) Class.forName(!Platform.isForge() ? "dev.architectury.core.item.ArchitecturyBucketItem" : "dev.architectury.core.item.forge.imitator.ArchitecturyBucketItem") .getDeclaredConstructor(Supplier.class, Item.Properties.class) - .newInstance(TestRegistries.TEST_FLUID, new Item.Properties()); + .newInstance(TestRegistries.TEST_FLUID, new Item.Properties().arch$tab(TestCreativeTabs.TEST_TAB)); } catch (InstantiationException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { throw new RuntimeException(e); @@ -180,9 +180,9 @@ public class TestRegistries { }); public static final RegistrySupplier TEST_BLOCK_ITEM = ITEMS.register("test_block", () -> - new BlockItem(TEST_BLOCK.get(), new Item.Properties())); + new BlockItem(TEST_BLOCK.get(), new Item.Properties().arch$tab(TestCreativeTabs.TEST_TAB))); public static final RegistrySupplier COLLISION_BLOCK_ITEM = ITEMS.register("collision_block", () -> - new BlockItem(COLLISION_BLOCK.get(), new Item.Properties())); + new BlockItem(COLLISION_BLOCK.get(), new Item.Properties().arch$tab(TestCreativeTabs.TEST_TAB))); public static final RegistrySupplier> TEST_ENTITY = ENTITY_TYPES.register("test_entity", TestEntity.TYPE); public static final RegistrySupplier> TEST_ENTITY_2 = ENTITY_TYPES.register("test_entity_2", TestEntity.TYPE_2); diff --git a/testmod-common/src/main/java/dev/architectury/test/tab/TestCreativeTabs.java b/testmod-common/src/main/java/dev/architectury/test/tab/TestCreativeTabs.java index f1ed76ef..ec3b6be4 100644 --- a/testmod-common/src/main/java/dev/architectury/test/tab/TestCreativeTabs.java +++ b/testmod-common/src/main/java/dev/architectury/test/tab/TestCreativeTabs.java @@ -28,14 +28,5 @@ import net.minecraft.world.item.ItemStack; public class TestCreativeTabs { public static final CreativeModeTab TEST_TAB = CreativeTabRegistry.create(new ResourceLocation(TestMod.MOD_ID, "test_tab"), - () -> new ItemStack(TestRegistries.TEST_ITEM.get()), (featureFlagSet, output) -> { - output.accept(TestRegistries.TEST_ITEM.get()); - output.accept(TestRegistries.TEST_EQUIPPABLE.get()); - output.accept(TestRegistries.TEST_EDIBLE.get()); - output.accept(TestRegistries.TEST_SPAWN_EGG.get()); - output.accept(TestRegistries.TEST_SPAWN_EGG_2.get()); - output.accept(TestRegistries.TEST_FLUID_BUCKET.get()); - output.accept(TestRegistries.TEST_BLOCK_ITEM.get()); - output.accept(TestRegistries.COLLISION_BLOCK_ITEM.get()); - }); + () -> new ItemStack(TestRegistries.TEST_ITEM.get())); } diff --git a/testmod-common/src/main/resources/architectury.common.json b/testmod-common/src/main/resources/architectury.common.json new file mode 100644 index 00000000..c3f28aa6 --- /dev/null +++ b/testmod-common/src/main/resources/architectury.common.json @@ -0,0 +1,31 @@ +{ + "injected_interfaces": { + "net/minecraft/class_1792": [ + "dev/architectury/extensions/injected/InjectedItemExtension" + ], + "net/minecraft/class_1792$class_1793": [ + "dev/architectury/extensions/injected/InjectedItemPropertiesExtension" + ], + "net/minecraft/class_2248": [ + "dev/architectury/extensions/injected/InjectedBlockExtension" + ], + "net/minecraft/class_3611": [ + "dev/architectury/extensions/injected/InjectedFluidExtension" + ], + "net/minecraft/class_1299": [ + "dev/architectury/extensions/injected/InjectedEntityTypeExtension" + ], + "net/minecraft/class_1755": [ + "dev/architectury/extensions/injected/InjectedBucketItemExtension" + ], + "net/minecraft/class_5712": [ + "dev/architectury/extensions/injected/InjectedGameEventExtension" + ], + "net/minecraft/class_4174$class_4175": [ + "dev/architectury/extensions/injected/InjectedFoodPropertiesBuilderExtension" + ], + "net/minecraft/class_2404": [ + "dev/architectury/extensions/injected/InjectedLiquidBlockExtension" + ] + } +} \ No newline at end of file