diff options
| author | shedaniel <daniel@shedaniel.me> | 2024-04-16 01:42:49 +0900 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2024-04-16 01:42:49 +0900 |
| commit | 9bdb9cb7c0a03accb6f86bcedff4b22f38f1346f (patch) | |
| tree | bc7557eeebd32609fc8b26db28f613e5fd576366 /default-plugin | |
| parent | f59653ff2a7c3641624928478a3622e6ffd32889 (diff) | |
| parent | 8981a2f730942e169ba5efa2f25ad3066dc0f797 (diff) | |
| download | RoughlyEnoughItems-9bdb9cb7c0a03accb6f86bcedff4b22f38f1346f.tar.gz RoughlyEnoughItems-9bdb9cb7c0a03accb6f86bcedff4b22f38f1346f.tar.bz2 RoughlyEnoughItems-9bdb9cb7c0a03accb6f86bcedff4b22f38f1346f.zip | |
Merge branch 'feature/12.1' into feature/13.1
# Conflicts:
# gradle.properties
# runtime/src/main/java/me/shedaniel/rei/impl/client/gui/changelog/ChangelogLoader.java
# runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/UncertainDisplayViewingScreen.java
# runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryWidget.java
# runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/OverflowWidget.java
Diffstat (limited to 'default-plugin')
13 files changed, 919 insertions, 20 deletions
diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java index ea61c622f..2764ca379 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java @@ -27,6 +27,7 @@ import com.google.common.collect.*; import dev.architectury.event.EventResult; import dev.architectury.networking.NetworkManager; import dev.architectury.platform.Platform; +import it.unimi.dsi.fastutil.objects.Object2FloatMap; import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; import it.unimi.dsi.fastutil.objects.ReferenceSet; @@ -36,6 +37,7 @@ import me.shedaniel.rei.api.client.favorites.FavoriteEntryType; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.client.registry.category.CategoryRegistry; import me.shedaniel.rei.api.client.registry.display.DisplayRegistry; +import me.shedaniel.rei.api.client.registry.entry.CollapsibleEntryRegistry; import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; import me.shedaniel.rei.api.client.registry.screen.ExclusionZones; import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry; @@ -43,6 +45,7 @@ import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry; import me.shedaniel.rei.api.client.registry.transfer.simple.SimpleTransferHandler; import me.shedaniel.rei.api.common.entry.EntryIngredient; import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; import me.shedaniel.rei.api.common.util.EntryIngredients; import me.shedaniel.rei.api.common.util.EntryStacks; import me.shedaniel.rei.impl.ClientInternals; @@ -54,6 +57,7 @@ import me.shedaniel.rei.plugin.client.categories.beacon.DefaultBeaconBaseCategor import me.shedaniel.rei.plugin.client.categories.beacon.DefaultBeaconPaymentCategory; import me.shedaniel.rei.plugin.client.categories.cooking.DefaultCookingCategory; import me.shedaniel.rei.plugin.client.categories.crafting.DefaultCraftingCategory; +import me.shedaniel.rei.plugin.client.categories.crafting.filler.*; import me.shedaniel.rei.plugin.client.categories.tag.DefaultTagCategory; import me.shedaniel.rei.plugin.client.exclusionzones.DefaultPotionEffectExclusionZones; import me.shedaniel.rei.plugin.client.exclusionzones.DefaultRecipeBookExclusionZones; @@ -72,7 +76,6 @@ import me.shedaniel.rei.plugin.common.displays.cooking.DefaultBlastingDisplay; import me.shedaniel.rei.plugin.common.displays.cooking.DefaultSmeltingDisplay; import me.shedaniel.rei.plugin.common.displays.cooking.DefaultSmokingDisplay; import me.shedaniel.rei.plugin.common.displays.crafting.DefaultCraftingDisplay; -import me.shedaniel.rei.plugin.common.displays.crafting.DefaultCustomDisplay; import me.shedaniel.rei.plugin.common.displays.tag.DefaultTagDisplay; import me.shedaniel.rei.plugin.common.displays.tag.TagNodes; import net.fabricmc.api.EnvType; @@ -113,6 +116,19 @@ import java.util.stream.Stream; @Environment(EnvType.CLIENT) @ApiStatus.Internal public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin { + private static final CraftingRecipeFiller<?>[] CRAFTING_RECIPE_FILLERS = new CraftingRecipeFiller[]{ + new TippedArrowRecipeFiller(), + new ShulkerBoxColoringFiller(), + new BannerDuplicateRecipeFiller(), + new ShieldDecorationRecipeFiller(), + new SuspiciousStewRecipeFiller(), + new BookCloningRecipeFiller(), + new FireworkRocketRecipeFiller(), + new ArmorDyeRecipeFiller(), + new MapCloningRecipeFiller(), + new MapExtendingRecipeFiller() + }; + public DefaultClientPlugin() { ClientInternals.attachInstance((Supplier<Object>) () -> this, "builtinClientPlugin"); } @@ -178,6 +194,24 @@ public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin } @Override + public void registerCollapsibleEntries(CollapsibleEntryRegistry registry) { + registry.group(new ResourceLocation("roughlyenoughitems", "enchanted_book"), Component.translatable("item.minecraft.enchanted_book"), + stack -> stack.getType() == VanillaEntryTypes.ITEM && stack.<ItemStack>castValue().is(Items.ENCHANTED_BOOK)); + registry.group(new ResourceLocation("roughlyenoughitems", "potion"), Component.translatable("item.minecraft.potion"), + stack -> stack.getType() == VanillaEntryTypes.ITEM && stack.<ItemStack>castValue().is(Items.POTION)); + registry.group(new ResourceLocation("roughlyenoughitems", "splash_potion"), Component.translatable("item.minecraft.splash_potion"), + stack -> stack.getType() == VanillaEntryTypes.ITEM && stack.<ItemStack>castValue().is(Items.SPLASH_POTION)); + registry.group(new ResourceLocation("roughlyenoughitems", "lingering_potion"), Component.translatable("item.minecraft.lingering_potion"), + stack -> stack.getType() == VanillaEntryTypes.ITEM && stack.<ItemStack>castValue().is(Items.LINGERING_POTION)); + registry.group(new ResourceLocation("roughlyenoughitems", "spawn_egg"), Component.translatable("text.rei.spawn_egg"), + stack -> stack.getType() == VanillaEntryTypes.ITEM && stack.<ItemStack>castValue().getItem() instanceof SpawnEggItem); + registry.group(new ResourceLocation("roughlyenoughitems", "tipped_arrow"), Component.translatable("item.minecraft.tipped_arrow"), + stack -> stack.getType() == VanillaEntryTypes.ITEM && stack.<ItemStack>castValue().is(Items.TIPPED_ARROW)); + registry.group(new ResourceLocation("roughlyenoughitems", "music_disc"), Component.translatable("text.rei.music_disc"), + stack -> stack.getType() == VanillaEntryTypes.ITEM && stack.<ItemStack>castValue().getItem() instanceof RecordItem); + } + + @Override public void registerCategories(CategoryRegistry registry) { registry.add( new DefaultCraftingCategory(), @@ -228,6 +262,10 @@ public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin return EventResult.pass(); }); + for (CraftingRecipeFiller<?> filler : CRAFTING_RECIPE_FILLERS) { + filler.registerCategories(registry); + } + Set<Item> axes = Sets.newHashSet(), hoes = Sets.newHashSet(), shovels = Sets.newHashSet(); EntryRegistry.getInstance().getEntryStacks().filter(stack -> stack.getValueType() == ItemStack.class).map(stack -> ((ItemStack) stack.getValue()).getItem()).forEach(item -> { if (item instanceof AxeItem && axes.add(item)) { @@ -289,25 +327,9 @@ public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin for (Map.Entry<Item, Integer> entry : AbstractFurnaceBlockEntity.getFuel().entrySet()) { registry.add(new DefaultFuelDisplay(Collections.singletonList(EntryIngredients.of(entry.getKey())), Collections.emptyList(), entry.getValue())); } - EntryIngredient arrowStack = EntryIngredient.of(EntryStacks.of(Items.ARROW)); - ReferenceSet<Potion> registeredPotions = new ReferenceOpenHashSet<>(); - EntryRegistry.getInstance().getEntryStacks().filter(entry -> entry.getValueType() == ItemStack.class && entry.<ItemStack>castValue().getItem() == Items.LINGERING_POTION).forEach(entry -> { - ItemStack itemStack = (ItemStack) entry.getValue(); - Potion potion = PotionUtils.getPotion(itemStack); - if (registeredPotions.add(potion)) { - List<EntryIngredient> input = new ArrayList<>(); - for (int i = 0; i < 4; i++) - input.add(arrowStack); - input.add(EntryIngredients.of(itemStack)); - for (int i = 0; i < 4; i++) - input.add(arrowStack); - ItemStack outputStack = new ItemStack(Items.TIPPED_ARROW, 8); - PotionUtils.setPotion(outputStack, potion); - PotionUtils.setCustomEffects(outputStack, PotionUtils.getCustomEffects(itemStack)); - EntryIngredient output = EntryIngredients.of(outputStack); - registry.add(new DefaultCustomDisplay(null, input, Collections.singletonList(output))); - } - }); + for (CraftingRecipeFiller<?> filler : CRAFTING_RECIPE_FILLERS) { + filler.registerDisplays(registry); + } if (ComposterBlock.COMPOSTABLES.isEmpty()) { ComposterBlock.bootStrap(); } diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ArmorDyeRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ArmorDyeRecipeFiller.java new file mode 100644 index 000000000..2582beb51 --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ArmorDyeRecipeFiller.java @@ -0,0 +1,87 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.plugin.client.categories.crafting.filler; + +import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryIngredients; +import me.shedaniel.rei.plugin.common.displays.crafting.DefaultCustomShapelessDisplay; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.DyeItem; +import net.minecraft.world.item.DyeableLeatherItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.ArmorDyeRecipe; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Random; + +public class ArmorDyeRecipeFiller implements CraftingRecipeFiller<ArmorDyeRecipe> { + @Override + public Collection<Display> apply(ArmorDyeRecipe recipe) { + List<Display> displays = new ArrayList<>(); + List<EntryStack<?>> toDye = EntryRegistry.getInstance().getEntryStacks().filter(entry -> entry.getValueType() == ItemStack.class && entry.<ItemStack>castValue().getItem() instanceof DyeableLeatherItem).toList(); + DyeColor[] colors = DyeColor.values(); + + for (EntryStack<?> armor : toDye) { + ItemStack armorStack = armor.castValue(); + for (DyeColor color : colors) { + ItemStack output = armorStack.copy(); + DyeItem dyeItem = DyeItem.byColor(color); + output = DyeableLeatherItem.dyeArmor(output, List.of(dyeItem)); + displays.add(new DefaultCustomShapelessDisplay(recipe, + List.of(EntryIngredient.of(armor.copy()), + EntryIngredients.of(dyeItem)), + List.of(EntryIngredients.of(output)))); + } + + for (int i = 0; i < 9; i++) { + int dyes = new Random().nextInt(2) + 2; + List<EntryIngredient> inputs = new ArrayList<>(); + List<DyeItem> dyeItems = new ArrayList<>(); + inputs.add(EntryIngredient.of(armor.copy())); + for (int j = 0; j < dyes; j++) { + DyeColor color = colors[new Random().nextInt(colors.length)]; + DyeItem dyeItem = DyeItem.byColor(color); + dyeItems.add(dyeItem); + inputs.add(EntryIngredients.of(dyeItem)); + } + ItemStack output = armorStack.copy(); + output = DyeableLeatherItem.dyeArmor(output, dyeItems); + displays.add(new DefaultCustomShapelessDisplay(recipe, + inputs, List.of(EntryIngredients.of(output)))); + } + } + + return displays; + } + + @Override + public Class<ArmorDyeRecipe> getRecipeClass() { + return ArmorDyeRecipe.class; + } +} diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/BannerDuplicateRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/BannerDuplicateRecipeFiller.java new file mode 100644 index 000000000..127355293 --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/BannerDuplicateRecipeFiller.java @@ -0,0 +1,70 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.plugin.client.categories.crafting.filler; + +import com.mojang.datafixers.util.Pair; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryStacks; +import me.shedaniel.rei.plugin.common.displays.crafting.DefaultCustomShapelessDisplay; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.BannerDuplicateRecipe; + +import java.util.*; + +public class BannerDuplicateRecipeFiller implements CraftingRecipeFiller<BannerDuplicateRecipe> { + @Override + public Collection<Display> apply(BannerDuplicateRecipe recipe) { + List<Display> displays = new ArrayList<>(); + Map<DyeColor, Pair<EntryIngredient.Builder, EntryStack<?>>> displayMap = new HashMap<>(); + + for (Pair<DyeColor, ItemStack> pair : ShieldDecorationRecipeFiller.randomizeBanners()) { + Optional<Item> bannerOptional = BuiltInRegistries.ITEM.getOptional(new ResourceLocation(pair.getFirst().getName() + "_banner")); + if (bannerOptional.isEmpty()) continue; + Pair<EntryIngredient.Builder, EntryStack<?>> builderPair = displayMap.computeIfAbsent(pair.getFirst(), color -> Pair.of(EntryIngredient.builder(), EntryStacks.of(bannerOptional.get()))); + builderPair.getFirst().add(EntryStacks.of(pair.getSecond())); + } + + for (Pair<EntryIngredient.Builder, EntryStack<?>> pair : displayMap.values()) { + EntryIngredient inputsFirst = pair.getFirst().build(); + EntryStack<?> inputsSecond = pair.getSecond(); + EntryIngredient.unifyFocuses(inputsFirst); + displays.add(new DefaultCustomShapelessDisplay(recipe, + List.of(inputsFirst, EntryIngredient.of(inputsSecond)), + List.of(inputsFirst))); + } + + return displays; + } + + @Override + public Class<BannerDuplicateRecipe> getRecipeClass() { + return BannerDuplicateRecipe.class; + } +} diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/BookCloningRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/BookCloningRecipeFiller.java new file mode 100644 index 000000000..74b3c0101 --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/BookCloningRecipeFiller.java @@ -0,0 +1,104 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.plugin.client.categories.crafting.filler; + +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.api.common.util.EntryStacks; +import me.shedaniel.rei.plugin.common.displays.crafting.DefaultCustomShapelessDisplay; +import net.minecraft.nbt.IntTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.WrittenBookItem; +import net.minecraft.world.item.crafting.BookCloningRecipe; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Random; + +public class BookCloningRecipeFiller implements CraftingRecipeFiller<BookCloningRecipe> { + private static final String[] TITLES = new String[]{ + "Adventurer's Dreams", "Adventurer's Diary", "The Lost Journal", + "The Lost Diary", "The Lost Book", "The Lost Tome", "The Lost Codex", + "The Last Journal", "The Last Diary", "The Last Book", "The Last Tome", + "Secrets of the World", "Secrets of the Universe", "Secrets of the Cosmos", + "Myths of the World", "Myths of the Universe", "Myths of the Cosmos", + "Old Tales of the World", "Old Tales of the Universe", "Old Tales of the Cosmos", + "The World of the Legends", "The Universe of the Heroes", "The Cosmos of the Gods", + "Diary of a Villager", "Diary of a Farmer", "Diary of a Fisherman", + "Dungeon Journal", "Dungeon Diary", "Dungeon Book", "Dungeon Tome", + "Dunk Memes", "Top 10 Memes of 2019", "Top 10 Memes of 2020", + "Plastic Memories", "Kizumonogatari" + }; + private static final String[] AUTHORS = new String[]{ + "shedaniel", "Steve", "Alex", "Notch", "Herobrine", "God", + "Santa Claus", "The Easter Bunny", "The Tooth Fairy" + }; + + @Override + public Collection<Display> apply(BookCloningRecipe recipe) { + List<Display> displays = new ArrayList<>(); + + for (int i = 1; i <= 8; i++) { + EntryIngredient.Builder[] inputs = new EntryIngredient.Builder[9]; + for (int j = 0; j < 9; j++) { + inputs[j] = EntryIngredient.builder(); + } + EntryIngredient.Builder output = EntryIngredient.builder(); + for (int j = 0; j < 10; j++) { + ItemStack writtenBook = generateBook(); + ItemStack bookAndQuill = new ItemStack(Items.WRITABLE_BOOK); + inputs[0].add(EntryStacks.of(writtenBook)); + for (int k = 0; k < i; k++) { + inputs[k + 1].add(EntryStacks.of(bookAndQuill)); + } + ItemStack cloned = writtenBook.copy(); + cloned.addTagElement(WrittenBookItem.TAG_GENERATION, IntTag.valueOf(1)); + cloned.setCount(i); + output.add(EntryStacks.of(cloned)); + } + displays.add(new DefaultCustomShapelessDisplay(recipe, + CollectionUtils.map(inputs, EntryIngredient.Builder::build), + List.of(output.build()))); + } + + return displays; + } + + private ItemStack generateBook() { + ItemStack stack = new ItemStack(Items.WRITTEN_BOOK); + stack.addTagElement(WrittenBookItem.TAG_AUTHOR, StringTag.valueOf(AUTHORS[new Random().nextInt(AUTHORS.length)])); + stack.addTagElement(WrittenBookItem.TAG_TITLE, StringTag.valueOf(TITLES[new Random().nextInt(TITLES.length)])); + stack.addTagElement(WrittenBookItem.TAG_GENERATION, IntTag.valueOf(0)); + return stack; + } + + @Override + public Class<BookCloningRecipe> getRecipeClass() { + return BookCloningRecipe.class; + } +} diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/CraftingRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/CraftingRecipeFiller.java new file mode 100644 index 000000000..ac575045b --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/CraftingRecipeFiller.java @@ -0,0 +1,92 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.plugin.client.categories.crafting.filler; + +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.DisplayRenderer; +import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.registry.category.CategoryRegistry; +import me.shedaniel.rei.api.client.registry.display.DisplayCategoryView; +import me.shedaniel.rei.api.client.registry.display.DisplayRegistry; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.plugin.common.BuiltinPlugin; +import me.shedaniel.rei.plugin.common.displays.crafting.DefaultCraftingDisplay; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.crafting.CraftingRecipe; +import net.minecraft.world.item.crafting.RecipeType; + +import java.util.Collection; +import java.util.List; +import java.util.function.Function; + +public interface CraftingRecipeFiller<T extends CraftingRecipe> extends Function<T, Collection<Display>> { + default void registerCategories(CategoryRegistry registry) { + } + + default void registerExtension(CategoryRegistry registry, ExtensionCallback callback) { + registry.get(BuiltinPlugin.CRAFTING).registerExtension((display, category, lastView) -> { + if (getRecipeClass().isInstance(display.getOptionalRecipe().orElse(null))) { + return new DisplayCategoryView<>() { + @Override + public DisplayRenderer getDisplayRenderer(DefaultCraftingDisplay<?> display) { + return lastView.getDisplayRenderer(display); + } + + @Override + public List<Widget> setupDisplay(DefaultCraftingDisplay<?> display, Rectangle bounds) { + List<Widget> widgets = lastView.setupDisplay(display, bounds); + callback.accept(bounds, widgets, display); + return widgets; + } + }; + } else { + return lastView; + } + }); + } + + default void registerDisplays(DisplayRegistry registry) { + registry.registerRecipesFiller(getRecipeClass(), RecipeType.CRAFTING, this::apply); + } + + default Widget createInfoWidget(Rectangle rectangle, DefaultCraftingDisplay<?> display, Component... texts) { + Point point = new Point(rectangle.getMaxX() - 4, rectangle.y + 4); + Rectangle bounds = new Rectangle(point.getX() - 9, point.getY() + 1, 8, 8); + if (display.isShapeless()) { + bounds.x -= 10; + } + Widget widget = Widgets.createTexturedWidget(new ResourceLocation("roughlyenoughitems:textures/gui/info.png"), bounds.getX(), bounds.getY(), 0, 0, bounds.getWidth(), bounds.getHeight(), 1, 1, 1, 1); + return Widgets.withTooltip(Widgets.withBounds(widget, bounds), texts); + } + + Class<T> getRecipeClass(); + + @FunctionalInterface + interface ExtensionCallback { + void accept(Rectangle bounds, List<Widget> widgets, DefaultCraftingDisplay<?> display); + } +} diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/FireworkRocketRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/FireworkRocketRecipeFiller.java new file mode 100644 index 000000000..d4a689df1 --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/FireworkRocketRecipeFiller.java @@ -0,0 +1,78 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.plugin.client.categories.crafting.filler; + +import me.shedaniel.rei.api.client.registry.category.CategoryRegistry; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryIngredients; +import me.shedaniel.rei.api.common.util.EntryStacks; +import me.shedaniel.rei.plugin.common.displays.crafting.DefaultCustomShapelessDisplay; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.FireworkRocketRecipe; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class FireworkRocketRecipeFiller implements CraftingRecipeFiller<FireworkRocketRecipe> { + @Override + public Collection<Display> apply(FireworkRocketRecipe recipe) { + List<Display> displays = new ArrayList<>(); + { + EntryIngredient[] inputs = new EntryIngredient[4]; + inputs[0] = EntryIngredients.of(Items.GUNPOWDER); + inputs[1] = EntryIngredients.of(Items.PAPER); + inputs[2] = EntryIngredient.of(EntryStack.empty().cast(), EntryStacks.of(Items.GUNPOWDER), EntryStacks.of(Items.GUNPOWDER)); + inputs[3] = EntryIngredient.of(EntryStack.empty().cast(), EntryStack.empty().cast(), EntryStacks.of(Items.GUNPOWDER)); + EntryStack<ItemStack>[] outputs = new EntryStack[3]; + for (int i = 0; i < 3; i++) { + outputs[i] = EntryStacks.of(new ItemStack(Items.FIREWORK_ROCKET, 3)); + CompoundTag tag = outputs[i].getValue().getOrCreateTagElement("Fireworks"); + tag.putByte("Flight", (byte) (i + 1)); + } + displays.add(new DefaultCustomShapelessDisplay(recipe, + List.of(inputs), + List.of(EntryIngredient.of(outputs)))); + } + + return displays; + } + + @Override + public Class<FireworkRocketRecipe> getRecipeClass() { + return FireworkRocketRecipe.class; + } + + @Override + public void registerCategories(CategoryRegistry registry) { + registerExtension(registry, (bounds, widgets, display) -> { + widgets.add(createInfoWidget(bounds, display, Component.translatable("text.rei.crafting.firework.gunpowder.amount"))); + }); + } +} diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/MapCloningRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/MapCloningRecipeFiller.java new file mode 100644 index 000000000..e36a6fd8f --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/MapCloningRecipeFiller.java @@ -0,0 +1,52 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons t |
