From d8b8a083eac13e1a1bc46c256a80497f70c1f03d Mon Sep 17 00:00:00 2001 From: shedaniel Date: Fri, 17 Jun 2022 17:52:20 +0800 Subject: Make gamemode favorites not pinned by default --- .../main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'default-plugin/src/main/java/me') 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..ec6c8edaa 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 @@ -350,7 +350,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) -- cgit From 4213c947730e4949b7cba5ea6bb249c9be035ab0 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Mon, 20 Jun 2022 17:23:47 +0800 Subject: Migrate EntryIngredient and EntryStack save() to saveIngredient() and saveStack() --- .../rei/plugin/common/displays/DefaultInformationDisplay.java | 2 +- .../rei/plugin/common/displays/brewing/DefaultBrewingDisplay.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'default-plugin/src/main/java/me') diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/DefaultInformationDisplay.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/DefaultInformationDisplay.java index fbae4fb85..dfa768002 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/DefaultInformationDisplay.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/DefaultInformationDisplay.java @@ -104,7 +104,7 @@ public class DefaultInformationDisplay implements Display { return new DisplaySerializer() { @Override public CompoundTag save(CompoundTag tag, DefaultInformationDisplay display) { - tag.put("stacks", display.getEntryStacks().save()); + tag.put("stacks", display.getEntryStacks().saveIngredient()); tag.putString("name", Component.Serializer.toJson(display.getName())); ListTag descriptions = new ListTag(); for (Component text : display.getTexts()) { diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/brewing/DefaultBrewingDisplay.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/brewing/DefaultBrewingDisplay.java index dda76169c..eb6dc3df1 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/brewing/DefaultBrewingDisplay.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/brewing/DefaultBrewingDisplay.java @@ -96,9 +96,9 @@ public class DefaultBrewingDisplay implements Display { return new DisplaySerializer() { @Override public CompoundTag save(CompoundTag tag, DefaultBrewingDisplay display) { - tag.put("input", display.input.save()); - tag.put("reactant", display.reactant.save()); - tag.put("output", display.output.save()); + tag.put("input", display.input.saveIngredient()); + tag.put("reactant", display.reactant.saveIngredient()); + tag.put("output", display.output.saveStack()); return tag; } -- cgit From 699259500bf8a54fe65f5503e59d6cfb696ba721 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Tue, 21 Jun 2022 00:01:14 +0800 Subject: Add tag helper methods in EntryIngredients --- .../rei/plugin/client/DefaultClientPlugin.java | 40 ++++++++-------------- 1 file changed, 14 insertions(+), 26 deletions(-) (limited to 'default-plugin/src/main/java/me') 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 ec6c8edaa..5e514af3d 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; @@ -75,12 +75,9 @@ 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; @@ -195,32 +192,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.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.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.castValue().getItem())) registry.addWorkstations(PATHING, stack); } } - private static Iterable resolveTag(TagKey tagKey) { - Registry registry = ((Registry>) Registry.REGISTRY).get((ResourceKey>) tagKey.registry()); - HolderSet.Named holders = registry.getTag(tagKey).orElse(null); - if (holders == null) return Collections.emptyList(); - return () -> holders.stream() - .map(Holder::value) - .iterator(); - } - - private static Iterable 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 @@ -271,8 +259,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()))); }); -- cgit From 81b82416abb2a94c12638fdbb08df2ac0f83254f Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sun, 26 Jun 2022 03:33:14 +0800 Subject: WIP on Tag Category, add Overflow Widget --- .../rei/plugin/client/DefaultClientPlugin.java | 18 ++ .../client/categories/tag/DefaultTagCategory.java | 138 ++++++++++++++ .../shedaniel/rei/plugin/common/BuiltinPlugin.java | 3 + .../common/displays/tag/DefaultTagDisplay.java | 98 ++++++++++ .../rei/plugin/common/displays/tag/TagNode.java | 135 ++++++++++++++ .../rei/plugin/common/displays/tag/TagNodes.java | 206 +++++++++++++++++++++ 6 files changed, 598 insertions(+) create mode 100644 default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/DefaultTagCategory.java create mode 100644 default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/tag/DefaultTagDisplay.java create mode 100644 default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/tag/TagNode.java create mode 100644 default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/tag/TagNodes.java (limited to 'default-plugin/src/main/java/me') 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 5e514af3d..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 @@ -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,6 +72,7 @@ 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.*; @@ -160,6 +162,7 @@ public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin new DefaultWaxScrapingCategory(), new DefaultOxidizingCategory(), new DefaultOxidationScrapingCategory(), + new DefaultTagCategory(), new DefaultInformationCategory() ); @@ -222,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 entry : AbstractFurnaceBlockEntity.getFuel().entrySet()) { registry.add(new DefaultFuelDisplay(Collections.singletonList(EntryIngredients.of(entry.getKey())), Collections.emptyList(), entry.getValue())); } @@ -305,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 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..c79cc9eb3 --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/DefaultTagCategory.java @@ -0,0 +1,138 @@ +/* + * 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 me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.api.client.gui.widgets.DelegateWidget; +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.registry.display.DisplayCategory; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +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.GuiComponent; +import net.minecraft.core.Registry; +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 java.util.ArrayList; +import java.util.List; + +public class DefaultTagCategory implements DisplayCategory> { + @Override + public CategoryIdentifier> 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 setupDisplay(DefaultTagDisplay display, Rectangle bounds) { + List widgets = new ArrayList<>(); + + widgets.add(Widgets.createRecipeBase(bounds)); + Rectangle innerBounds = new Rectangle(bounds.x + 6 + 14, bounds.y + 6, bounds.width - 12 - 14, bounds.height - 12); + widgets.add(Widgets.createSlotBase(innerBounds)); + + Widget[] delegate = new Widget[]{Widgets.noOp()}; + TagNode[] tagNode = new TagNode[]{null}; + Rectangle overflowBounds = new Rectangle(innerBounds.x + 1, innerBounds.y + 1, innerBounds.width - 2, innerBounds.height - 2); + WidgetWithBounds inner = Widgets.withBounds(new DelegateWidget(Widgets.noOp()) { + @Override + protected Widget delegate() { + return delegate[0]; + } + }, overflowBounds); + widgets.add(Widgets.withTranslate(Widgets.overflowed(overflowBounds, Widgets.withBounds(Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> { + new GuiComponent() { + { + fillGradient(matrices, 0, 0, 1000, 1000, 0xff3489eb, 0xffc41868); + for (int x = 0; x < 20; x++) { + for (int y = 0; y < 20; y++) { + Widgets.createSlot(new Point(500 - 9 * 20 + x * 18, 500 - 9 * 20 + y * 18)) + .entry(EntryStacks.of(Registry.ITEM.byId(x + y * 10 + 1))) + .disableBackground() + .render(matrices, mouseX, mouseY, delta); + } + } + } + }; + }), new Rectangle(0, 0, 1000, 1000))), 0, 0, 20)); + + TagNodes.create(display.getKey(), dataResult -> { + if (dataResult.error().isPresent()) { + delegate[0] = 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())) + ); + } else { + tagNode[0] = dataResult.result().get(); + } + }); + + widgets.add(Widgets.createButton(new Rectangle(bounds.x + 5, bounds.y + 6, 13, 13), new TextComponent("")) + .onRender((poseStack, button) -> { + button.setEnabled(tagNode[0] != null); + }) + .onClick(button -> { + }) + .tooltipLine(new TranslatableComponent("text.rei.expand.view"))); + widgets.add(Widgets.createButton(new Rectangle(bounds.x + 5, bounds.getMaxY() - 6 - 13, 13, 13), 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(Widgets.createTexturedWidget(new ResourceLocation("roughlyenoughitems", "textures/gui/expand.png"), + new Rectangle(bounds.x + 5 + 2, bounds.y + 6 + 2, 13 - 4, 13 - 4), 0, 0, 9, 9), 0, 0, 10)); + widgets.add(Widgets.withTranslate(Widgets.createTexturedWidget(new ResourceLocation("roughlyenoughitems", "textures/gui/clipboard.png"), + new Rectangle(bounds.x + 5 + 2, bounds.getMaxY() - 6 - 13 + 2, 13 - 4, 13 - 4), 0, 0, 9, 9), 0, 0.5, 10)); + + return widgets; + } +} diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/BuiltinPlugin.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/BuiltinPlugin.java index cd5797473..ad3cdb29a 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/BuiltinPlugin.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/BuiltinPlugin.java @@ -33,6 +33,7 @@ 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.tag.DefaultTagDisplay; import org.jetbrains.annotations.ApiStatus; public interface BuiltinPlugin { @@ -60,5 +61,7 @@ public interface BuiltinPlugin { CategoryIdentifier OXIDIZING = CategoryIdentifier.of("minecraft", "plugins/oxidizing"); @ApiStatus.Experimental CategoryIdentifier OXIDATION_SCRAPING = CategoryIdentifier.of("minecraft", "plugins/oxidation_scraping"); + @ApiStatus.Experimental + CategoryIdentifier> TAG = CategoryIdentifier.of("minecraft", "plugins/tag"); CategoryIdentifier INFO = CategoryIdentifier.of("roughlyenoughitems", "plugins/information"); } diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/tag/DefaultTagDisplay.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/tag/DefaultTagDisplay.java new file mode 100644 index 000000000..09c453019 --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/tag/DefaultTagDisplay.java @@ -0,0 +1,98 @@ +/* + * 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.common.displays.tag; + +import dev.architectury.fluid.FluidStack; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +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.CollectionUtils; +import me.shedaniel.rei.api.common.util.EntryIngredients; +import me.shedaniel.rei.api.common.util.EntryStacks; +import me.shedaniel.rei.plugin.common.BuiltinPlugin; +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.material.Fluid; +import org.jetbrains.annotations.ApiStatus; + +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +@ApiStatus.Experimental +public class DefaultTagDisplay implements Display { + private final TagKey key; + private final Function, EntryStack> mapper; + private final List ingredients; + + public DefaultTagDisplay(TagKey key, Function, EntryStack> mapper) { + this.key = key; + this.mapper = mapper; + this.ingredients = CollectionUtils.map(EntryIngredients.ofTag(key, mapper), EntryIngredient::of); + } + + public static DefaultTagDisplay ofItems(TagKey key) { + return new DefaultTagDisplay<>(key, DefaultTagDisplay::extractItem); + } + + public static DefaultTagDisplay ofFluids(TagKey key) { + return new DefaultTagDisplay<>(key, DefaultTagDisplay::extractFluid); + } + + private static EntryStack extractItem(Holder holder) { + return EntryStacks.of(holder.value()); + } + + private static EntryStack extractFluid(Holder holder) { + return EntryStacks.of(holder.value()); + } + + @Override + public List getInputEntries() { + return this.ingredients; + } + + @Override + public List getOutputEntries() { + return this.ingredients; + } + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return BuiltinPlugin.TAG; + } + + @Override + public Optional getDisplayLocation() { + return Optional.of(key.location()); + } + + public TagKey getKey() { + return key; + } +} diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/tag/TagNode.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/tag/TagNode.java new file mode 100644 index 000000000..94b5b047d --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/tag/TagNode.java @@ -0,0 +1,135 @@ +/* + * 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.common.displays.tag; + +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.TagKey; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +@ApiStatus.Internal +public abstract class TagNode { + private final List> children; + + public TagNode() { + this.children = new ArrayList<>(); + } + + public static TagNode ofValue(Holder value) { + return new ValueTagNode<>(value); + } + + public static TagNode ofReference(TagKey key) { + return new ReferenceTagNode<>(key); + } + + public List> children() { + return children; + } + + public void addChild(TagNode child) { + children.add(child); + } + + public void addValueChild(Holder child) { + children.add(ofValue(child)); + } + + public void addReferenceChild(TagKey child) { + children.add(ofReference(child)); + } + + public String asTree() { + StringBuilder buffer = new StringBuilder(50); + printTree(buffer, "", ""); + return buffer.toString(); + } + + private void printTree(StringBuilder buffer, String prefix, String childrenPrefix) { + buffer.append(prefix); + buffer.append(asText()); + buffer.append('\n'); + for (Iterator> it = children.iterator(); it.hasNext(); ) { + TagNode next = it.next(); + if (it.hasNext()) { + next.printTree(buffer, childrenPrefix + "├── ", childrenPrefix + "│ "); + } else { + next.printTree(buffer, childrenPrefix + "└── ", childrenPrefix + " "); + } + } + } + + protected abstract String asText(); + + @Nullable + public Holder getValue() { + return null; + } + + @Nullable + public TagKey getReference() { + return null; + } + + private static class ValueTagNode extends TagNode { + private final Holder value; + + public ValueTagNode(Holder value) { + this.value = value; + } + + @Override + public Holder getValue() { + return value; + } + + @Override + protected String asText() { + return value.unwrapKey().map(ResourceKey::location).orElse(null) + ""; + } + } + + private static class ReferenceTagNode extends TagNode { + private final TagKey key; + + public ReferenceTagNode(TagKey key) { + this.key = key; + } + + @Override + public TagKey getReference() { + return key; + } + + @Override + protected String asText() { + return key.location() + ""; + } + } +} diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/tag/TagNodes.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/tag/TagNodes.java new file mode 100644 index 000000000..832249cc2 --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/common/displays/tag/TagNodes.java @@ -0,0 +1,206 @@ +/* + * 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.common.displays.tag; + +import com.mojang.serialization.DataResult; +import dev.architectury.event.events.client.ClientLifecycleEvent; +import dev.architectury.networking.NetworkManager; +import dev.architectury.networking.transformers.SplitPacketTransformer; +import dev.architectury.utils.Env; +import dev.architectury.utils.EnvExecutor; +import io.netty.buffer.Unpooled; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.Minecraft; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.tags.Tag; +import net.minecraft.tags.TagKey; +import org.jetbrains.annotations.ApiStatus; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Consumer; + +@ApiStatus.Internal +public class TagNodes { + public static final ResourceLocation REQUEST_TAGS_PACKET_C2S = new ResourceLocation("roughlyenoughitems", "request_tags_c2s"); + public static final ResourceLocation REQUEST_TAGS_PACKET_S2C = new ResourceLocation("roughlyenoughitems", "request_tags_s2c"); + + public static final Map>> TAG_DIR_MAP = new HashMap<>(); + public static final ThreadLocal CURRENT_TAG_DIR = new ThreadLocal<>(); + public static final Map, RawTagData>> RAW_TAG_DATA_MAP = new ConcurrentHashMap<>(); + public static final Map>, Map> TAG_DATA_MAP = new HashMap<>(); + public static Map>, Consumer>>>> requestedTags = new HashMap<>(); + + public record RawTagData(List otherElements, List otherTags) { + } + + public record TagData(IntList otherElements, List otherTags) { + private static TagData fromNetwork(FriendlyByteBuf buf) { + int count = buf.readVarInt(); + IntList otherElements = new IntArrayList(count + 1); + for (int i = 0; i < count; i++) { + otherElements.add(buf.readVarInt()); + } + count = buf.readVarInt(); + List otherTags = new ArrayList<>(count + 1); + for (int i = 0; i < count; i++) { + otherTags.add(buf.readResourceLocation()); + } + return new TagData(otherElements, otherTags); + } + + private void toNetwork(FriendlyByteBuf buf) { + buf.writeVarInt(otherElements.size()); + for (int integer : otherElements) { + buf.writeVarInt(integer); + } + buf.writeVarInt(otherTags.size()); + for (ResourceLocation tag : otherTags) { + writeResourceLocation(buf, tag); + } + } + } + + private static void writeResourceLocation(FriendlyByteBuf buf, ResourceLocation location) { + if (location.getNamespace().equals("minecraft")) { + buf.writeUtf(location.getPath()); + } else { + buf.writeUtf(location.toString()); + } + } + + public static void init() { + EnvExecutor.runInEnv(Env.CLIENT, () -> Client::init); + + NetworkManager.registerReceiver(NetworkManager.c2s(), REQUEST_TAGS_PACKET_C2S, Collections.singletonList(new SplitPacketTransformer()), (buf, context) -> { + UUID uuid = buf.readUUID(); + ResourceKey> resourceKey = ResourceKey.createRegistryKey(buf.readResourceLocation()); + FriendlyByteBuf newBuf = new FriendlyByteBuf(Unpooled.buffer()); + newBuf.writeUUID(uuid); + Map dataMap = TAG_DATA_MAP.getOrDefault(resourceKey, Collections.emptyMap()); + newBuf.writeInt(dataMap.size()); + for (Map.Entry entry : dataMap.entrySet()) { + writeResourceLocation(newBuf, entry.getKey()); + entry.getValue().toNetwork(newBuf); + } + NetworkManager.sendToPlayer((ServerPlayer) context.getPlayer(), REQUEST_TAGS_PACKET_S2C, newBuf); + }); + } + + @Environment(EnvType.CLIENT) + public static void requestTagData(ResourceKey> resourceKey, Consumer>> callback) { + if (Minecraft.getInstance().getSingleplayerServer() != null) { + callback.accept(DataResult.success(TAG_DATA_MAP.get(resourceKey))); + } else if (!NetworkManager.canServerReceive(REQUEST_TAGS_PACKET_C2S)) { + callback.accept(DataResult.error("Cannot request tags from server")); + } else if (requestedTags.containsKey(resourceKey)) { + requestedTags.get(resourceKey).accept(callback); + callback.accept(DataResult.success(TAG_DATA_MAP.getOrDefault(resourceKey, Collections.emptyMap()))); + } else { + FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer()); + UUID uuid = UUID.randomUUID(); + buf.writeUUID(uuid); + buf.writeResourceLocation(resourceKey.location()); + Client.nextUUID = uuid; + Client.nextResourceKey = resourceKey; + List>>> callbacks = new CopyOnWriteArrayList<>(); + callbacks.add(callback); + Client.nextCallback = mapDataResult -> { + requestedTags.put(resourceKey, c -> c.accept(mapDataResult)); + for (Consumer>> consumer : callbacks) { + consumer.accept(mapDataResult); + } + }; + requestedTags.put(resourceKey, callbacks::add); + NetworkManager.sendToServer(REQUEST_TAGS_PACKET_C2S, buf); + } + } + + private static class Client { + public static UUID nextUUID; + public static ResourceKey> nextResourceKey; + public static Consumer>> nextCallback; + + private static void init() { + ClientLifecycleEvent.CLIENT_LEVEL_LOAD.register(world -> { + requestedTags.clear(); + }); + NetworkManager.registerReceiver(NetworkManager.s2c(), REQUEST_TAGS_PACKET_S2C, Collections.singletonList(new SplitPacketTransformer()), (buf, context) -> { + UUID uuid = buf.readUUID(); + if (nextUUID.equals(uuid)) { + Map map = new HashMap<>(); + int count = buf.readInt(); + for (int i = 0; i < count; i++) { + map.put(buf.readResourceLocation(), TagData.fromNetwork(buf)); + } + + TAG_DATA_MAP.put(nextResourceKey, map); + nextCallback.accept(DataResult.success(map)); + + nextUUID = null; + nextResourceKey = null; + nextCallback = null; + } + }); + } + } + + public static void create(TagKey tagKey, Consumer>> callback) { + Registry registry = ((Registry>) Registry.REGISTRY).get((ResourceKey>) tagKey.registry()); + requestTagData(tagKey.registry(), result -> { + callback.accept(result.flatMap(dataMap -> resolveTag(tagKey, registry, dataMap))); + }); + } + + private static DataResult> resolveTag(TagKey tagKey, Registry registry, Map tagDataMap) { + TagData tagData = tagDataMap.get(tagKey.location()); + if (tagData == null) return DataResult.error("Tag Missing: " + tagKey.location()); + + TagNode self = TagNode.ofReference(tagKey); + for (int element : tagData.otherElements()) { + Optional> holder = registry.getHolder(element); + if (holder.isPresent()) { + self.addValueChild(holder.get()); + } + } + for (ResourceLocation childTagId : tagData.otherTags()) { + TagKey childTagKey = TagKey.create(tagKey.registry(), childTagId); + if (registry.getTag(childTagKey).isPresent()) { + DataResult> result = resolveTag(childTagKey, registry, tagDataMap); + if (result.error().isPresent()) return DataResult.error(result.error().get().message()); + self.addChild(result.result().get()); + } + } + return DataResult.success(self); + } +} -- cgit From f4ec48ad1539bdc0ea5f54931740adf4bcb0560b Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sun, 26 Jun 2022 04:09:06 +0800 Subject: Adapt scissors to transform --- .../categories/DefaultInformationCategory.java | 21 ++++++++------- .../beacon/DefaultBeaconBaseCategory.java | 31 ++++++++++------------ .../beacon/DefaultBeaconPaymentCategory.java | 31 ++++++++++------------ .../client/categories/tag/DefaultTagCategory.java | 6 ++--- 4 files changed, 42 insertions(+), 47 deletions(-) (limited to 'default-plugin/src/main/java/me') 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= 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 Date: Sun, 26 Jun 2022 21:45:36 +0800 Subject: Primitive tags category implementation --- .../client/categories/tag/DefaultTagCategory.java | 38 +++---- .../categories/tag/ReferenceTagNodeWidget.java | 83 ++++++++++++++ .../client/categories/tag/TagNodeWidget.java | 43 ++++++++ .../client/categories/tag/TagTreeWidget.java | 122 +++++++++++++++++++++ .../client/categories/tag/TagTreesWidget.java | 48 ++++++++ .../client/categories/tag/ValueTagNodeWidget.java | 103 +++++++++++++++++ .../common/displays/tag/DefaultTagDisplay.java | 4 + .../rei/plugin/common/displays/tag/TagNode.java | 58 +++++----- .../rei/plugin/common/displays/tag/TagNodes.java | 7 +- 9 files changed, 455 insertions(+), 51 deletions(-) create mode 100644 default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/ReferenceTagNodeWidget.java create mode 100644 default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagNodeWidget.java create mode 100644 default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagTreeWidget.java create mode 100644 default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagTreesWidget.java create mode 100644 default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/ValueTagNodeWidget.java (limited to 'default-plugin/src/main/java/me') 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 index 07d5fe985..49ebb91ca 100644 --- 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 @@ -26,7 +26,7 @@ package me.shedaniel.rei.plugin.client.categories.tag; import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.gui.Renderer; -import me.shedaniel.rei.api.client.gui.widgets.DelegateWidget; +import me.shedaniel.rei.api.client.gui.widgets.DelegateWidgetWithBounds; 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; @@ -38,8 +38,6 @@ 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.GuiComponent; -import net.minecraft.core.Registry; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TranslatableComponent; @@ -73,39 +71,31 @@ public class DefaultTagCategory implements DisplayCategory[] tagNode = new TagNode[]{null}; Rectangle overflowBounds = new Rectangle(innerBounds.x + 1, innerBounds.y + 1, innerBounds.width - 2, innerBounds.height - 2); - WidgetWithBounds inner = Widgets.withBounds(new DelegateWidget(Widgets.noOp()) { + widgets.add(Widgets.withTranslate(Widgets.overflowed(overflowBounds, new DelegateWidgetWithBounds(Widgets.noOp(), Rectangle::new) { @Override - protected Widget delegate() { + protected WidgetWithBounds delegate() { return delegate[0]; } - }, overflowBounds); - widgets.add(Widgets.withTranslate(Widgets.overflowed(overflowBounds, Widgets.withBounds(Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> { - new GuiComponent() { - { - fillGradient(matrices, 0, 0, 1000, 1000, 0xff3489eb, 0xffc41868); - for (int x = 0; x < 10; x++) { - for (int y = 0; y < 10; y++) { - Widgets.createSlot(new Point(500 - 9 * 10 + x * 18, 500 - 9 * 10 + y * 18)) - .entry(EntryStacks.of(Registry.ITEM.byId(x + y * 10 + 1))) - .disableBackground() - .render(matrices, mouseX, mouseY, delta); - } - } - } - }; - }), new Rectangle(0, 0, 1000, 1000))), 0, 0, 20)); + + @Override + public Rectangle getBounds() { + return delegate().getBounds(); + } + }), 0, 0, 20)); TagNodes.create(display.getKey(), dataResult -> { if (dataResult.error().isPresent()) { - delegate[0] = Widgets.concat( + 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 + delegate[0] = Widgets.padded(16, new TagTreeWidget(tagNode[0], display.getMapper())); } }); 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 extends TagNodeWidget { + private final TagNode node; + private final Rectangle bounds; + private final Slot slot; + private final List children; + + public ReferenceTagNodeWidget(TagNode node, Function, EntryStack> 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.getBounds().getWidth() / 2, bounds.y + (bounds.height - this.slot.getBounds().getHeight()) / 2 + 1); + this.slot.render(poses, mouseX, mouseY, delta); + if (this.containsMouse(mouseX, mouseY)) { + Tooltip.create(new TextComponent("#" + this.node.getReference().location().toString())).queue(); + } + } + + @Override + public List children() { + return children; + } +} diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagNodeWidget.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagNodeWidget.java new file mode 100644 index 000000000..9f2216935 --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin