diff options
Diffstat (limited to 'default-plugin/src/main/java/me')
16 files changed, 1138 insertions, 75 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 729f48cc1..7f1a2926d 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 @@ -43,7 +43,7 @@ import me.shedaniel.rei.api.client.registry.screen.ExclusionZones; import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry; import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry; import me.shedaniel.rei.api.common.entry.EntryIngredient; -import me.shedaniel.rei.api.common.util.CollectionUtils; +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.impl.ClientInternals; @@ -54,6 +54,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.tag.DefaultTagCategory; import me.shedaniel.rei.plugin.client.exclusionzones.DefaultPotionEffectExclusionZones; import me.shedaniel.rei.plugin.client.exclusionzones.DefaultRecipeBookExclusionZones; import me.shedaniel.rei.plugin.client.favorites.GameModeFavoriteEntry; @@ -71,16 +72,14 @@ 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 net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.gui.screens.inventory.*; import net.minecraft.client.gui.screens.recipebook.RecipeUpdateListener; -import net.minecraft.core.Holder; -import net.minecraft.core.HolderSet; import net.minecraft.core.Registry; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.BlockTags; import net.minecraft.tags.ItemTags; @@ -163,6 +162,7 @@ public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin new DefaultWaxScrapingCategory(), new DefaultOxidizingCategory(), new DefaultOxidationScrapingCategory(), + new DefaultTagCategory(), new DefaultInformationCategory() ); @@ -195,32 +195,23 @@ public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin registry.addWorkstations(PATHING, EntryStacks.of(item)); } }); - for (Item item : getTag(new ResourceLocation("c", "axes"))) { - if (axes.add(item)) { - registry.addWorkstations(STRIPPING, EntryStacks.of(item)); - registry.addWorkstations(WAX_SCRAPING, EntryStacks.of(item)); - registry.addWorkstations(OXIDATION_SCRAPING, EntryStacks.of(item)); + for (EntryStack<?> stack : getTag(new ResourceLocation("c", "axes"))) { + if (axes.add(stack.<ItemStack>castValue().getItem())) { + registry.addWorkstations(STRIPPING, stack); + registry.addWorkstations(WAX_SCRAPING, stack); + registry.addWorkstations(OXIDATION_SCRAPING, stack); } } - for (Item item : getTag(new ResourceLocation("c", "hoes"))) { - if (hoes.add(item)) registry.addWorkstations(TILLING, EntryStacks.of(item)); + for (EntryStack<?> stack : getTag(new ResourceLocation("c", "hoes"))) { + if (hoes.add(stack.<ItemStack>castValue().getItem())) registry.addWorkstations(TILLING, stack); } - for (Item item : getTag(new ResourceLocation("c", "shovels"))) { - if (shovels.add(item)) registry.addWorkstations(PATHING, EntryStacks.of(item)); + for (EntryStack<?> stack : getTag(new ResourceLocation("c", "shovels"))) { + if (shovels.add(stack.<ItemStack>castValue().getItem())) registry.addWorkstations(PATHING, stack); } } - private static <T> Iterable<T> resolveTag(TagKey<T> tagKey) { - Registry<T> registry = ((Registry<Registry<T>>) Registry.REGISTRY).get((ResourceKey<Registry<T>>) tagKey.registry()); - HolderSet.Named<T> holders = registry.getTag(tagKey).orElse(null); - if (holders == null) return Collections.emptyList(); - return () -> holders.stream() - .map(Holder::value) - .iterator(); - } - - private static Iterable<Item> getTag(ResourceLocation tagId) { - return resolveTag(TagKey.create(Registry.ITEM_REGISTRY, tagId)); + private static EntryIngredient getTag(ResourceLocation tagId) { + return EntryIngredients.ofItemTag(TagKey.create(Registry.ITEM_REGISTRY, tagId)); } @Override @@ -234,6 +225,17 @@ public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin registry.registerRecipeFiller(UpgradeRecipe.class, RecipeType.SMITHING, DefaultSmithingDisplay::new); registry.registerFiller(AnvilRecipe.class, DefaultAnvilDisplay::new); registry.registerFiller(BrewingRecipe.class, DefaultBrewingDisplay::new); + registry.registerFiller(TagKey.class, tagKey -> { + if (tagKey.isFor(Registry.ITEM_REGISTRY)) { + return DefaultTagDisplay.ofItems(tagKey); + } else if (tagKey.isFor(Registry.BLOCK_REGISTRY)) { + return DefaultTagDisplay.ofItems(tagKey); + } else if (tagKey.isFor(Registry.FLUID_REGISTRY)) { + return DefaultTagDisplay.ofFluids(tagKey); + } + + return null; + }); for (Map.Entry<Item, Integer> entry : AbstractFurnaceBlockEntity.getFuel().entrySet()) { registry.add(new DefaultFuelDisplay(Collections.singletonList(EntryIngredients.of(entry.getKey())), Collections.emptyList(), entry.getValue())); } @@ -271,8 +273,8 @@ public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin DummyShovelItem.getPathBlocksMap().entrySet().stream().sorted(Comparator.comparing(b -> Registry.BLOCK.getKey(b.getKey()))).forEach(set -> { registry.add(new DefaultPathingDisplay(EntryStacks.of(set.getKey()), EntryStacks.of(set.getValue().getBlock()))); }); - registry.add(new DefaultBeaconBaseDisplay(CollectionUtils.map(resolveTag(BlockTags.BEACON_BASE_BLOCKS), ItemStack::new))); - registry.add(new DefaultBeaconPaymentDisplay(CollectionUtils.map(resolveTag(ItemTags.BEACON_PAYMENT_ITEMS), ItemStack::new))); + registry.add(new DefaultBeaconBaseDisplay(Collections.singletonList(EntryIngredients.ofItemTag(BlockTags.BEACON_BASE_BLOCKS)), Collections.emptyList())); + registry.add(new DefaultBeaconPaymentDisplay(Collections.singletonList(EntryIngredients.ofItemTag(ItemTags.BEACON_PAYMENT_ITEMS)), Collections.emptyList())); HoneycombItem.WAXABLES.get().entrySet().stream().sorted(Comparator.comparing(b -> Registry.BLOCK.getKey(b.getKey()))).forEach(set -> { registry.add(new DefaultWaxingDisplay(EntryStacks.of(set.getKey()), EntryStacks.of(set.getValue()))); }); @@ -317,6 +319,10 @@ public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin } else { registerForgePotions(registry, this); } + + for (Registry<?> reg : Registry.REGISTRY) { + reg.getTags().forEach(tagPair -> registry.add(tagPair.getFirst())); + } } @ExpectPlatform @@ -350,7 +356,7 @@ public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin public void registerFavorites(FavoriteEntryType.Registry registry) { registry.register(GameModeFavoriteEntry.ID, GameModeFavoriteEntry.Type.INSTANCE); registry.getOrCrateSection(new TranslatableComponent(GameModeFavoriteEntry.TRANSLATION_KEY)) - .add(true, Stream.concat( + .add(Stream.concat( Arrays.stream(GameType.values()) .filter(type -> type.getId() >= 0), Stream.of((GameType) null) diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/DefaultInformationCategory.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/DefaultInformationCategory.java index 5cb04c7cd..0f7baf641 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/DefaultInformationCategory.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/DefaultInformationCategory.java @@ -36,6 +36,7 @@ import me.shedaniel.rei.api.client.REIRuntime; import me.shedaniel.rei.api.client.gui.AbstractRenderer; import me.shedaniel.rei.api.client.gui.DisplayRenderer; import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.api.client.gui.widgets.CloseableScissors; import me.shedaniel.rei.api.client.gui.widgets.Widget; import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; import me.shedaniel.rei.api.client.gui.widgets.Widgets; @@ -194,18 +195,18 @@ public class DefaultInformationCategory implements DisplayCategory<DefaultInform public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { scrolling.updatePosition(delta); Rectangle innerBounds = scrolling.getScissorBounds(); - ScissorsHandler.INSTANCE.scissor(innerBounds); - int currentY = -scrolling.scrollAmountInt() + innerBounds.y; - for (FormattedCharSequence text : texts) { - if (text != null && currentY + font.lineHeight >= innerBounds.y && currentY <= innerBounds.getMaxY()) { - font.draw(matrices, text, innerBounds.x + 2, currentY + 2, REIRuntime.getInstance().isDarkThemeEnabled() ? 0xFFBBBBBB : 0xFF090909); + try (CloseableScissors scissors = scissor(matrices, innerBounds)) { + int currentY = -scrolling.scrollAmountInt() + innerBounds.y; + for (FormattedCharSequence text : texts) { + if (text != null && currentY + font.lineHeight >= innerBounds.y && currentY <= innerBounds.getMaxY()) { + font.draw(matrices, text, innerBounds.x + 2, currentY + 2, REIRuntime.getInstance().isDarkThemeEnabled() ? 0xFFBBBBBB : 0xFF090909); + } + currentY += text == null ? 4 : font.lineHeight; } - currentY += text == null ? 4 : font.lineHeight; } - ScissorsHandler.INSTANCE.removeLastScissor(); - ScissorsHandler.INSTANCE.scissor(scrolling.getBounds()); - scrolling.renderScrollBar(0xff000000, 1, REIRuntime.getInstance().isDarkThemeEnabled() ? 0.8f : 1f); - ScissorsHandler.INSTANCE.removeLastScissor(); + try (CloseableScissors scissors = scissor(matrices, scrolling.getBounds())) { + scrolling.renderScrollBar(0xff000000, 1, REIRuntime.getInstance().isDarkThemeEnabled() ? 0.8f : 1f); + } } @Override diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/beacon/DefaultBeaconBaseCategory.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/beacon/DefaultBeaconBaseCategory.java index d2dd424cf..645457e13 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/beacon/DefaultBeaconBaseCategory.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/beacon/DefaultBeaconBaseCategory.java @@ -33,10 +33,7 @@ import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.REIRuntime; import me.shedaniel.rei.api.client.gui.DisplayRenderer; import me.shedaniel.rei.api.client.gui.Renderer; -import me.shedaniel.rei.api.client.gui.widgets.Slot; -import me.shedaniel.rei.api.client.gui.widgets.Widget; -import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; -import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.gui.widgets.*; import me.shedaniel.rei.api.client.registry.display.DisplayCategory; import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.util.CollectionUtils; @@ -158,21 +155,21 @@ public class DefaultBeaconBaseCategory implements DisplayCategory<DefaultBeaconB public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { scrolling.updatePosition(delta); Rectangle innerBounds = scrolling.getScissorBounds(); - ScissorsHandler.INSTANCE.scissor(innerBounds); - for (int y = 0; y < Mth.ceil(widgets.size() / 8f); y++) { - for (int x = 0; x < 8; x++) { - int index = y * 8 + x; - if (widgets.size() <= index) - break; - Slot widget = widgets.get(index); - widget.getBounds().setLocation(bounds.x + 1 + x * 18, bounds.y + 1 + y * 18 - scrolling.scrollAmountInt()); - widget.render(matrices, mouseX, mouseY, delta); + try (CloseableScissors scissors = scissor(matrices, innerBounds)) { + for (int y = 0; y < Mth.ceil(widgets.size() / 8f); y++) { + for (int x = 0; x < 8; x++) { + int index = y * 8 + x; + if (widgets.size() <= index) + break; + Slot widget = widgets.get(index); + widget.getBounds().setLocation(bounds.x + 1 + x * 18, bounds.y + 1 + y * 18 - scrolling.scrollAmountInt()); + widget.render(matrices, mouseX, mouseY, delta); + } } } - ScissorsHandler.INSTANCE.removeLastScissor(); - ScissorsHandler.INSTANCE.scissor(scrolling.getBounds()); - scrolling.renderScrollBar(0xff000000, 1, REIRuntime.getInstance().isDarkThemeEnabled() ? 0.8f : 1f); - ScissorsHandler.INSTANCE.removeLastScissor(); + try (CloseableScissors scissors = scissor(matrices, scrolling.getBounds())) { + scrolling.renderScrollBar(0xff000000, 1, REIRuntime.getInstance().isDarkThemeEnabled() ? 0.8f : 1f); + } } @Override diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/beacon/DefaultBeaconPaymentCategory.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/beacon/DefaultBeaconPaymentCategory.java index 71642fc1e..2b7f69b97 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/beacon/DefaultBeaconPaymentCategory.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/beacon/DefaultBeaconPaymentCategory.java @@ -33,10 +33,7 @@ import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.REIRuntime; import me.shedaniel.rei.api.client.gui.DisplayRenderer; import me.shedaniel.rei.api.client.gui.Renderer; -import me.shedaniel.rei.api.client.gui.widgets.Slot; -import me.shedaniel.rei.api.client.gui.widgets.Widget; -import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; -import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.gui.widgets.*; import me.shedaniel.rei.api.client.registry.display.DisplayCategory; import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.util.CollectionUtils; @@ -158,21 +155,21 @@ public class DefaultBeaconPaymentCategory implements DisplayCategory<DefaultBeac public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { scrolling.updatePosition(delta); Rectangle innerBounds = scrolling.getScissorBounds(); - ScissorsHandler.INSTANCE.scissor(innerBounds); - for (int y = 0; y < Mth.ceil(widgets.size() / 8f); y++) { - for (int x = 0; x < 8; x++) { - int index = y * 8 + x; - if (widgets.size() <= index) - break; - Slot widget = widgets.get(index); - widget.getBounds().setLocation(bounds.x + 1 + x * 18, bounds.y + 1 + y * 18 - scrolling.scrollAmountInt()); - widget.render(matrices, mouseX, mouseY, delta); + try (CloseableScissors scissors = scissor(matrices, innerBounds)) { + for (int y = 0; y < Mth.ceil(widgets.size() / 8f); y++) { + for (int x = 0; x < 8; x++) { + int index = y * 8 + x; + if (widgets.size() <= index) + break; + Slot widget = widgets.get(index); + widget.getBounds().setLocation(bounds.x + 1 + x * 18, bounds.y + 1 + y * 18 - scrolling.scrollAmountInt()); + widget.render(matrices, mouseX, mouseY, delta); + } } } - ScissorsHandler.INSTANCE.removeLastScissor(); - ScissorsHandler.INSTANCE.scissor(scrolling.getBounds()); - scrolling.renderScrollBar(0xff000000, 1, REIRuntime.getInstance().isDarkThemeEnabled() ? 0.8f : 1f); - ScissorsHandler.INSTANCE.removeLastScissor(); + try (CloseableScissors scissors = scissor(matrices, scrolling.getBounds())) { + scrolling.renderScrollBar(0xff000000, 1, REIRuntime.getInstance().isDarkThemeEnabled() ? 0.8f : 1f); + } } @Override diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/DefaultTagCategory.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/DefaultTagCategory.java new file mode 100644 index 000000000..24296cfaa --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/DefaultTagCategory.java @@ -0,0 +1,204 @@ +/* + * 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.tag; + +import com.mojang.blaze3d.platform.Window; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Matrix4f; +import me.shedaniel.clothconfig2.api.animator.ValueAnimator; +import me.shedaniel.math.FloatingRectangle; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.ClientHelper; +import me.shedaniel.rei.api.client.REIRuntime; +import me.shedaniel.rei.api.client.gui.AbstractRenderer; +import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.api.client.gui.widgets.*; +import me.shedaniel.rei.api.client.registry.display.DisplayCategory; +import me.shedaniel.rei.api.client.util.ClientEntryStacks; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.api.common.util.EntryStacks; +import me.shedaniel.rei.plugin.common.BuiltinPlugin; +import me.shedaniel.rei.plugin.common.displays.tag.DefaultTagDisplay; +import me.shedaniel.rei.plugin.common.displays.tag.TagNode; +import me.shedaniel.rei.plugin.common.displays.tag.TagNodes; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.core.Holder; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Items; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; + +public class DefaultTagCategory implements DisplayCategory<DefaultTagDisplay<?, ?>> { + @Override + public CategoryIdentifier<? extends DefaultTagDisplay<?, ?>> getCategoryIdentifier() { + return BuiltinPlugin.TAG; + } + + @Override + public Component getTitle() { + return new TranslatableComponent("category.rei.tag"); + } + + @Override + public Renderer getIcon() { + return EntryStacks.of(Items.NAME_TAG); + } + + @Override + public List<Widget> setupDisplay(DefaultTagDisplay<?, ?> display, Rectangle bounds) { + List<Widget> widgets = new ArrayList<>(); + + Window window = Minecraft.getInstance().getWindow(); + Rectangle boundsBig = new Rectangle(window.getGuiScaledWidth() * 0.05, window.getGuiScaledHeight() * 0.1, window.getGuiScaledWidth() * 0.9, window.getGuiScaledHeight() * 0.8); + Rectangle recipeBounds = bounds.clone(); + + boolean[] expanded = {false}; + + Rectangle innerBounds = new Rectangle(bounds.x + 6 + 14, bounds.y + 6, bounds.width - 12 - 14, bounds.height - 12); + Rectangle overflowBounds = new Rectangle(innerBounds.x + 1, innerBounds.y + 1, innerBounds.width - 2, innerBounds.height - 2); + + Rectangle expandButtonBounds = new Rectangle(bounds.x + 5, bounds.y + 6, 13, 13); + Rectangle expandOverlayBounds = new Rectangle(bounds.x + 5 + 2, bounds.y + 6 + 2, 13 - 4, 13 - 4); + Rectangle copyButtonBounds = new Rectangle(bounds.x + 5, bounds.getMaxY() - 6 - 13, 13, 13); + Rectangle copyOverlayBounds = new Rectangle(bounds.x + 5 + 2, bounds.getMaxY() - 6 - 13 + 2, 13 - 4, 13 - 4); + + ValueAnimator<FloatingRectangle> boundsAnimator = ValueAnimator.ofFloatingRectangle(bounds.getFloatingBounds()) + .withConvention(() -> { + if (expanded[0]) { + return boundsBig.getFloatingBounds(); + } else { + return bounds.getFloatingBounds(); + } + }, 1400); + + widgets.add(Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> { + innerBounds.setBounds(recipeBounds.x + 6 + 14, recipeBounds.y + 6, recipeBounds.width - 12 - 14, recipeBounds.height - 12); + overflowBounds.setBounds(innerBounds.x + 1, innerBounds.y + 1, innerBounds.width - 2, innerBounds.height - 2); + expandButtonBounds.setBounds(recipeBounds.x + 5, recipeBounds.y + 6, 13, 13); + copyButtonBounds.setBounds(recipeBounds.x + 5, recipeBounds.getMaxY() - 6 - 13, 13, 13); + expandOverlayBounds.setBounds(recipeBounds.x + 5 + 2, recipeBounds.y + 6 + 2, 13 - 4, 13 - 4); + copyOverlayBounds.setBounds(recipeBounds.x + 5 + 2, recipeBounds.getMaxY() - 6 - 13 + 2, 13 - 4, 13 - 4); + recipeBounds.setBounds(boundsAnimator.value()); + boundsAnimator.update(delta); + + if (overflowBounds.contains(mouseX, mouseY)) { + REIRuntime.getInstance().clearTooltips(); + } + })); + + widgets.add(Widgets.createRecipeBase(recipeBounds)); + widgets.add(Widgets.createSlotBase(innerBounds)); + + WidgetWithBounds[] delegate = new WidgetWithBounds[]{Widgets.noOp()}; + TagNode<?>[] tagNode = new TagNode[]{null}; + widgets.add(Widgets.withTranslate(Widgets.delegateWithBounds(() -> delegate[0]), 0, 0, 20)); + + TagNodes.create(display.getKey(), dataResult -> { + if (dataResult.error().isPresent()) { + delegate[0] = Widgets.withBounds(Widgets.concat( + Widgets.createLabel(new Point(innerBounds.getCenterX(), innerBounds.getCenterY() - 8), new TextComponent("Failed to resolve tags!")), + Widgets.createLabel(new Point(innerBounds.getCenterX(), innerBounds.getCenterY() - 8), new TextComponent(dataResult.error().get().message())) + ), overflowBounds); + } else { + tagNode[0] = dataResult.result().get(); + //noinspection rawtypes + Function<? extends Holder<?>, ? extends EntryStack<?>> displayMapper = display.getMapper(); + Function<Holder<?>, EntryStack<?>> mapper = holder -> { + EntryStack<?> stack = ((Function<Holder<?>, EntryStack<?>>) displayMapper).apply(holder); + if (stack.isEmpty()) { + return ClientEntryStacks.of(new AbstractRenderer() { + @Override + public void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { + Minecraft instance = Minecraft.getInstance(); + Font font = instance.font; + String text = "?"; + int width = font.width(text); + font.draw(matrices, text, bounds.getCenterX() - width / 2f + 0.2f, bounds.getCenterY() - font.lineHeight / 2f + 1f, REIRuntime.getInstance().isDarkThemeEnabled() ? -4473925 : -12566464); + } + + @Override + @Nullable + public Tooltip getTooltip(TooltipContext context) { + return Tooltip.create(context.getPoint(), new TextComponent(holder.unwrapKey().map(key -> key.location().toString()).orElse("null"))); + } + }); + } + return stack; + }; + delegate[0] = Widgets.overflowed(overflowBounds, Widgets.padded(16, new TagTreeWidget(tagNode[0], mapper))); + } + }); + + widgets.add(Widgets.createButton(expandButtonBounds, new TextComponent("")) + .onRender((poseStack, button) -> { + button.setEnabled(tagNode[0] != null); + }) + .onClick(button -> { + expanded[0] = !expanded[0]; + }) + .tooltipSupplier(button -> new Component[]{new TranslatableComponent(!expanded[0] ? "text.rei.expand.view" : "text.rei.expand.view.close")})); + widgets.add(Widgets.createButton(copyButtonBounds, new TextComponent("")) + .onRender((poseStack, button) -> { + button.setEnabled(tagNode[0] != null); + }) + .onClick(button -> { + TagNode<?> node = tagNode[0]; + + if (node != null) { + Minecraft.getInstance().keyboardHandler.setClipboard(node.asTree()); + } + }) + .tooltipLine(new TranslatableComponent("text.rei.tag.copy.clipboard"))); + widgets.add(Widgets.withTranslate(new DelegateWidget(Widgets.noOp()) { + @Override + protected Widget delegate() { + ResourceLocation expandTexture = !expanded[0] ? new ResourceLocation("roughlyenoughitems", "textures/gui/expand.png") + : new ResourceLocation("roughlyenoughitems", "textures/gui/shrink.png"); + return Widgets.concat( + Widgets.createTexturedWidget(expandTexture, + new Rectangle(recipeBounds.x + 5 + 2, recipeBounds.y + 6 + 2, 13 - 4, 13 - 4), 0, 0, 9, 9), + Widgets.createTexturedWidget(new ResourceLocation("roughlyenoughitems", "textures/gui/clipboard.png"), + new Rectangle(recipeBounds.x + 5 + 2, recipeBounds.getMaxY() - 6 - 13 + 2, 13 - 4, 13 - 4), 0, 0, 9, 9) + ); + } + }, 0, 0, 10)); + + Matrix4f translateMatrix = Matrix4f.createTranslateMatrix(0, 0, 200); + Matrix4f identity = new Matrix4f(); + identity.setIdentity(); + return CollectionUtils.map(widgets, widget -> Widgets.withTranslate(widget, () -> + expanded[0] || !boundsAnimator.value().equals(boundsAnimator.target()) ? translateMatrix : identity)); + } +} diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/ReferenceTagNodeWidget.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/ReferenceTagNodeWidget.java new file mode 100644 index 000000000..75beaf41c --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/ReferenceTagNodeWidget.java @@ -0,0 +1,83 @@ +/* + * 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.tag; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.widgets.Slot; +import me.shedaniel.rei.api.client.gui.widgets.Tooltip; +import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryIngredients; +import me.shedaniel.rei.plugin.common.displays.tag.TagNode; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.core.Holder; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.resources.ResourceLocation; + +import java.util.Collections; +import java.util.List; +import java.util.function.Function; + +public class ReferenceTagNodeWidget<S, T> extends TagNodeWidget<S, T> { + private final TagNode<S> node; + private final Rectangle bounds; + private final Slot slot; + private final List<? extends GuiEventListener> children; + + public ReferenceTagNodeWidget(TagNode<S> node, Function<Holder<S>, EntryStack<T>> mapper) { + this.node = node; + this.bounds = new Rectangle(0, 0, 24, 23); + this.slot = Widgets.createSlot(new Rectangle(0, 0, 18, 18)) + .disableBackground() + .disableHighlight() + .disableTooltips() + .entries(EntryIngredients.ofTag(node.getReference(), mapper)); + this.children = Collections.singletonList(this.slot); + } + + @Override + public Rectangle getBounds() { + return bounds; + } + + @Override + public void render(PoseStack poses, int mouseX, int mouseY, float delta) { + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderTexture(0, new ResourceLocation("textures/gui/advancements/widgets.png")); + this.blit(poses, bounds.x, bounds.y, 1, 128 + 27, 24, 24); + this.slot.getBounds().setLocation(bounds.getCenterX() - this.slot.getBo |
