diff options
| author | shedaniel <daniel@shedaniel.me> | 2022-12-18 20:50:56 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2024-04-16 00:38:17 +0900 |
| commit | ffe21652b40a93a00f33a27a5ecf41479b48bcd9 (patch) | |
| tree | 2861df1f563c35c78a1eda7477f6c201eed7ce56 | |
| parent | e6687c01b254bf903d4895aa0bb631b1679d465c (diff) | |
| download | RoughlyEnoughItems-ffe21652b40a93a00f33a27a5ecf41479b48bcd9.tar.gz RoughlyEnoughItems-ffe21652b40a93a00f33a27a5ecf41479b48bcd9.tar.bz2 RoughlyEnoughItems-ffe21652b40a93a00f33a27a5ecf41479b48bcd9.zip | |
Close #1131
4 files changed, 221 insertions, 41 deletions
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/registry/display/DisplayRegistry.java b/api/src/main/java/me/shedaniel/rei/api/client/registry/display/DisplayRegistry.java index fd34e4e84..b708a2e31 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/registry/display/DisplayRegistry.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/registry/display/DisplayRegistry.java @@ -212,7 +212,7 @@ public interface DisplayRegistry extends RecipeManagerContext<REIClientPlugin> { * Registers a display filler, to be filled during {@link #tryFillDisplay(Object)}. * <p> * Vanilla {@link Recipe} are by default filled, display filters - * can be used to automatically generate displaies for vanilla {@link Recipe}. + * can be used to automatically generate displays for vanilla {@link Recipe}. * * @param typeClass the type of {@code T} * @param filler the filler, taking a {@code T} and returning a {@code D} @@ -227,7 +227,23 @@ public interface DisplayRegistry extends RecipeManagerContext<REIClientPlugin> { * Registers a display filler, to be filled during {@link #tryFillDisplay(Object)}. * <p> * Vanilla {@link Recipe} are by default filled, display filters - * can be used to automatically generate displaies for vanilla {@link Recipe}. + * can be used to automatically generate displays for vanilla {@link Recipe}. + * + * @param typeClass the type of {@code T} + * @param filler the filler, taking a {@code T} and returning a {@code D} + * @param <T> the type of object + * @param <D> the type of display + */ + @ApiStatus.Experimental + default <T extends Recipe<?>, D extends Display> void registerRecipesFiller(Class<T> typeClass, RecipeType<? super T> recipeType, Function<? extends T, @Nullable Collection<? extends D>> filler) { + registerRecipesFiller(typeClass, type -> Objects.equals(recipeType, type), filler); + } + + /** + * Registers a display filler, to be filled during {@link #tryFillDisplay(Object)}. + * <p> + * Vanilla {@link Recipe} are by default filled, display filters + * can be used to automatically generate displays for vanilla {@link Recipe}. * * @param typeClass the type of {@code T} * @param filler the filler, taking a {@code T} and returning a {@code D} @@ -242,7 +258,23 @@ public interface DisplayRegistry extends RecipeManagerContext<REIClientPlugin> { * Registers a display filler, to be filled during {@link #tryFillDisplay(Object)}. * <p> * Vanilla {@link Recipe} are by default filled, display filters - * can be used to automatically generate displaies for vanilla {@link Recipe}. + * can be used to automatically generate displays for vanilla {@link Recipe}. + * + * @param typeClass the type of {@code T} + * @param filler the filler, taking a {@code T} and returning a {@code D} + * @param <T> the type of object + * @param <D> the type of display + */ + @ApiStatus.Experimental + default <T extends Recipe<?>, D extends Display> void registerRecipesFiller(Class<T> typeClass, Predicate<RecipeType<? super T>> recipeType, Function<? extends T, @Nullable Collection<? extends D>> filler) { + registerRecipesFiller(typeClass, recipeType, Predicates.alwaysTrue(), filler); + } + + /** + * Registers a display filler, to be filled during {@link #tryFillDisplay(Object)}. + * <p> + * Vanilla {@link Recipe} are by default filled, display filters + * can be used to automatically generate displays for vanilla {@link Recipe}. * * @param typeClass the type of {@code T} * @param filler the filler, taking a {@code T} and returning a {@code D} @@ -257,7 +289,23 @@ public interface DisplayRegistry extends RecipeManagerContext<REIClientPlugin> { * Registers a display filler, to be filled during {@link #tryFillDisplay(Object)}. * <p> * Vanilla {@link Recipe} are by default filled, display filters - * can be used to automatically generate displaies for vanilla {@link Recipe}. + * can be used to automatically generate displays for vanilla {@link Recipe}. + * + * @param typeClass the type of {@code T} + * @param filler the filler, taking a {@code T} and returning a {@code D} + * @param <T> the type of object + * @param <D> the type of display + */ + @ApiStatus.Experimental + default <T extends Recipe<?>, D extends Display> void registerRecipesFiller(Class<T> typeClass, Predicate<RecipeType<? super T>> recipeType, Predicate<? extends T> predicate, Function<? extends T, @Nullable Collection<? extends D>> filler) { + registerDisplaysFiller(typeClass, recipe -> recipeType.test((RecipeType<? super T>) recipe.getType()) && ((Predicate<T>) predicate).test(recipe), filler); + } + + /** + * Registers a display filler, to be filled during {@link #tryFillDisplay(Object)}. + * <p> + * Vanilla {@link Recipe} are by default filled, display filters + * can be used to automatically generate displays for vanilla {@link Recipe}. * * @param typeClass the type of {@code T} * @param filler the filler, taking a {@code T} and returning a {@code D} @@ -272,7 +320,23 @@ public interface DisplayRegistry extends RecipeManagerContext<REIClientPlugin> { * Registers a display filler, to be filled during {@link #tryFillDisplay(Object)}. * <p> * Vanilla {@link Recipe} are by default filled, display filters - * can be used to automatically generate displaies for vanilla {@link Recipe}. + * can be used to automatically generate displays for vanilla {@link Recipe}. + * + * @param typeClass the type of {@code T} + * @param filler the filler, taking a {@code T} and returning a {@code D} + * @param <T> the type of object + * @param <D> the type of display + */ + @ApiStatus.Experimental + default <T, D extends Display> void registerDisplaysFiller(Class<T> typeClass, Function<? extends T, @Nullable Collection<? extends D>> filler) { + registerDisplaysFiller(typeClass, Predicates.alwaysTrue(), filler); + } + + /** + * Registers a display filler, to be filled during {@link #tryFillDisplay(Object)}. + * <p> + * Vanilla {@link Recipe} are by default filled, display filters + * can be used to automatically generate displays for vanilla {@link Recipe}. * * @param typeClass the type of {@code T} * @param predicate the predicate of {@code T} @@ -286,7 +350,22 @@ public interface DisplayRegistry extends RecipeManagerContext<REIClientPlugin> { * Registers a display filler, to be filled during {@link #tryFillDisplay(Object)}. * <p> * Vanilla {@link Recipe} are by default filled, display filters - * can be used to automatically generate displaies for vanilla {@link Recipe}. + * can be used to automatically generate displays for vanilla {@link Recipe}. + * + * @param typeClass the type of {@code T} + * @param predicate the predicate of {@code T} + * @param filler the filler, taking a {@code T} and returning a {@code D} + * @param <T> the type of object + * @param <D> the type of display + */ + @ApiStatus.Experimental + <T, D extends Display> void registerDisplaysFiller(Class<T> typeClass, Predicate<? extends T> predicate, Function<? extends T, @Nullable Collection<? extends D>> filler); + + /** + * Registers a display filler, to be filled during {@link #tryFillDisplay(Object)}. + * <p> + * Vanilla {@link Recipe} are by default filled, display filters + * can be used to automatically generate displays for vanilla {@link Recipe}. * * @param typeClass the type of {@code T} * @param predicate the predicate of {@code T} and reason @@ -301,7 +380,22 @@ public interface DisplayRegistry extends RecipeManagerContext<REIClientPlugin> { * Registers a display filler, to be filled during {@link #tryFillDisplay(Object)}. * <p> * Vanilla {@link Recipe} are by default filled, display filters - * can be used to automatically generate displaies for vanilla {@link Recipe}. + * can be used to automatically generate displays for vanilla {@link Recipe}. + * + * @param typeClass the type of {@code T} + * @param predicate the predicate of {@code T} and reason + * @param filler the filler, taking a {@code T} and returning a {@code D} + * @param <T> the type of object + * @param <D> the type of display + */ + @ApiStatus.Experimental + <T, D extends Display> void registerDisplaysFiller(Class<T> typeClass, BiPredicate<? extends T, DisplayAdditionReasons> predicate, Function<? extends T, @Nullable Collection<? extends D>> filler); + + /** + * Registers a display filler, to be filled during {@link #tryFillDisplay(Object)}. + * <p> + * Vanilla {@link Recipe} are by default filled, display filters + * can be used to automatically generate displays for vanilla {@link Recipe}. * * @param predicate the predicate of the object * @param filler the filler, taking an object and returning a {@code D} @@ -310,6 +404,19 @@ public interface DisplayRegistry extends RecipeManagerContext<REIClientPlugin> { <D extends Display> void registerFiller(Predicate<?> predicate, Function<?, @Nullable D> filler); /** + * Registers a display filler, to be filled during {@link #tryFillDisplay(Object)}. + * <p> + * Vanilla {@link Recipe} are by default filled, display filters + * can be used to automatically generate displays for vanilla {@link Recipe}. + * + * @param predicate the predicate of the object + * @param filler the filler, taking an object and returning a {@code D} + * @param <D> the type of display + */ + @ApiStatus.Experimental + <D extends Display> void registerDisplaysFiller(Predicate<?> predicate, Function<?, @Nullable Collection<? extends D>> filler); + + /** * Tries to fill displays from {@code T}. * * @param value the object 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 bf1541003..50ffc35ef 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 @@ -29,6 +29,7 @@ import com.google.common.collect.Sets; 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.ReferenceOpenHashSet; import it.unimi.dsi.fastutil.objects.ReferenceSet; import me.shedaniel.math.Rectangle; @@ -55,6 +56,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.TippedArrowRecipeFiller; 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; @@ -73,7 +75,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; @@ -253,25 +254,7 @@ 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))); - } - }); + registry.registerRecipesFiller(TippedArrowRecipe.class, RecipeType.CRAFTING, new TippedArrowRecipeFiller()::apply); if (ComposterBlock.COMPOSTABLES.isEmpty()) { ComposterBlock.bootStrap(); } diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/TippedArrowRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/TippedArrowRecipeFiller.java new file mode 100644 index 000000000..014799f6f --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/TippedArrowRecipeFiller.java @@ -0,0 +1,71 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 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 it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; +import it.unimi.dsi.fastutil.objects.ReferenceSet; +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.util.EntryIngredients; +import me.shedaniel.rei.api.common.util.EntryStacks; +import me.shedaniel.rei.plugin.common.displays.crafting.DefaultCustomDisplay; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.crafting.TippedArrowRecipe; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.Function; + +public class TippedArrowRecipeFiller implements Function<TippedArrowRecipe, Collection<Display>> { + @Override + public Collection<Display> apply(TippedArrowRecipe recipe) { + EntryIngredient arrowStack = EntryIngredient.of(EntryStacks.of(Items.ARROW)); + ReferenceSet<Potion> registeredPotions = new ReferenceOpenHashSet<>(); + List<Display> displays = new ArrayList<>(); + + 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)); + displays.add(new DefaultCustomDisplay(recipe, input, List.of(EntryIngredients.of(outputStack)))); + } + }); + + return displays; + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayRegistryImpl.java index f8f303408..655466211 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayRegistryImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayRegistryImpl.java @@ -146,14 +146,31 @@ public class DisplayRegistryImpl extends RecipeManagerContextImpl<REIClientPlugi } @Override + public <T, D extends Display> void registerDisplaysFiller(Class<T> typeClass, Predicate<? extends T> predicate, Function<? extends T, @Nullable Collection<? extends D>> filler) { + registerDisplaysFiller(o -> typeClass.isInstance(o) && ((Predicate<T>) predicate).test((T) o), o -> ((Function<T, Collection<? extends D>>) filler).apply((T) o)); + } + + @Override public <T, D extends Display> void registerFiller(Class<T> typeClass, BiPredicate<? extends T, DisplayAdditionReasons> predicate, Function<? extends T, D> filler) { - fillers.add(new DisplayFiller<>((o, s) -> typeClass.isInstance(o) && ((BiPredicate<Object, DisplayAdditionReasons>) predicate).test(o, s), (Function<Object, D>) filler)); + fillers.add(DisplayFiller.of((o, s) -> typeClass.isInstance(o) && ((BiPredicate<Object, DisplayAdditionReasons>) predicate).test(o, s), (Function<Object, D>) filler)); + InternalLogger.getInstance().debug("Added display filter: %s for %s", filler, typeClass.getName()); + } + + @Override + public <T, D extends Display> void registerDisplaysFiller(Class<T> typeClass, BiPredicate<? extends T, DisplayAdditionReasons> predicate, Function<? extends T, @Nullable Collection<? extends D>> filler) { + fillers.add(new DisplayFiller<>((o, s) -> typeClass.isInstance(o) && ((BiPredicate<Object, DisplayAdditionReasons>) predicate).test(o, s), (Function<Object, Collection<? extends D>>) filler)); InternalLogger.getInstance().debug("Added display filter: %s for %s", filler, typeClass.getName()); } @Override public <D extends Display> void registerFiller(Predicate<?> predicate, Function<?, D> filler) { - fillers.add(new DisplayFiller<>((o, s) -> ((Predicate<Object>) predicate).test(o), (Function<Object, D>) filler)); + fillers.add(DisplayFiller.of((o, s) -> ((Predicate<Object>) predicate).test(o), (Function<Object, D>) filler)); + InternalLogger.getInstance().debug("Added display filter: %s", filler); + } + + @Override + public <D extends Display> void registerDisplaysFiller(Predicate<?> predicate, Function<?, @Nullable Collection<? extends D>> filler) { + fillers.add(new DisplayFiller<>((o, s) -> ((Predicate<Object>) predicate).test(o), (Function<Object, Collection<? extends D>>) filler)); InternalLogger.getInstance().debug("Added display filter: %s", filler); } @@ -194,28 +211,27 @@ public class DisplayRegistryImpl extends RecipeManagerContextImpl<REIClientPlugi @Override public <T> Collection<Display> tryFillDisplay(T value, DisplayAdditionReason... reason) { if (value instanceof Display) return Collections.singleton((Display) value); - List<Display> displays = null; + List<Display> out = null; DisplayAdditionReasons reasons = reason.length == 0 ? DisplayAdditionReasons.Impl.EMPTY : new DisplayAdditionReasons.Impl(reason); for (DisplayFiller<?> filler : fillers) { - Display display = tryFillDisplayGenerics(filler, value, reasons); - if (display != null) { - if (displays == null) displays = Collections.singletonList(display); - else { - if (!(displays instanceof ArrayList)) displays = new ArrayList<>(displays); - displays.add(display); + Collection<Display> displays = tryFillDisplayGenerics(filler, value, reasons); + if (displays != null && !displays.isEmpty()) { + if (out == null) out = new ArrayList<>(); + for (Display display : displays) { + if (display != null) out.add(display); } } } - if (displays != null) { - return displays; + if (out != null) { + return out; } return Collections.emptyList(); } - private <D extends Display> D tryFillDisplayGenerics(DisplayFiller<D> filler, Object value, DisplayAdditionReasons reasons) { + private <D extends Display> Collection<D> tryFillDisplayGenerics(DisplayFiller<? extends D> filler, Object value, DisplayAdditionReasons reasons) { try { if (filler.predicate.test(value, reasons)) { - return filler.mappingFunction.apply(value); + return (Collection<D>) filler.mappingFunction.apply(value); } } catch (Throwable e) { throw new RuntimeException("Failed to fill displays!", e); @@ -233,7 +249,10 @@ public class DisplayRegistryImpl extends RecipeManagerContextImpl<REIClientPlugi private record DisplayFiller<D extends Display>( BiPredicate<Object, DisplayAdditionReasons> predicate, - Function<Object, D> mappingFunction + Function<Object, Collection<? extends D>> mappingFunction ) { + public static <D extends Display> DisplayFiller<D> of(BiPredicate<Object, DisplayAdditionReasons> predicate, Function<Object, D> mappingFunction) { + return new DisplayFiller<>(predicate, o -> Collections.singleton(mappingFunction.apply(o))); + } } } |
