From 72e44a1432f831bdbd42f1c8a574bf22e8b4a481 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Tue, 22 Sep 2020 12:20:12 +0800 Subject: Fix #409 and more Signed-off-by: shedaniel --- .../java/me/shedaniel/rei/api/ClientHelper.java | 52 ++++++++++++++- .../java/me/shedaniel/rei/api/DisplayHelper.java | 23 +++---- .../me/shedaniel/rei/api/TextRepresentable.java | 6 +- .../java/me/shedaniel/rei/api/widgets/Label.java | 8 +++ .../shedaniel/rei/utils/ImmutableLiteralText.java | 14 +++- .../me/shedaniel/rei/plugin/DefaultPlugin.java | 3 +- .../shedaniel/rei/gui/ContainerScreenOverlay.java | 17 +++-- .../rei/gui/config/entry/FilteringScreen.java | 15 +++-- .../rei/gui/credits/CreditsEntryListWidget.java | 70 ++++++++++++++++++++ .../shedaniel/rei/gui/credits/CreditsScreen.java | 7 +- .../rei/gui/plugin/DefaultRuntimePlugin.java | 4 +- .../rei/gui/widget/EntryListEntryWidget.java | 6 +- .../shedaniel/rei/gui/widget/EntryListWidget.java | 74 +++++++++++++--------- .../rei/gui/widget/FavoritesListWidget.java | 30 +++++---- .../me/shedaniel/rei/impl/ClientHelperImpl.java | 34 +--------- .../me/shedaniel/rei/impl/ConfigObjectImpl.java | 2 +- .../me/shedaniel/rei/impl/FluidEntryStack.java | 16 ++--- .../me/shedaniel/rei/impl/InternalWidgets.java | 2 +- .../java/me/shedaniel/rei/impl/ItemEntryStack.java | 11 +--- .../me/shedaniel/rei/impl/TextTransformations.java | 21 ++++++ .../me/shedaniel/rei/impl/widgets/LabelWidget.java | 23 +++++-- .../src/main/resources/fabric.mod.json | 14 ++-- .../roughlyenoughitems-runtime.accessWidener | 3 + gradle.properties | 2 +- 24 files changed, 305 insertions(+), 152 deletions(-) create mode 100644 RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/TextTransformations.java diff --git a/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/ClientHelper.java b/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/ClientHelper.java index 73f768e8d..797e44ecb 100644 --- a/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/ClientHelper.java +++ b/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/ClientHelper.java @@ -25,12 +25,18 @@ package me.shedaniel.rei.api; import me.shedaniel.rei.impl.Internals; import me.shedaniel.rei.utils.CollectionUtils; +import me.shedaniel.rei.utils.FormattingUtils; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.chat.NarratorChatListener; +import net.minecraft.core.Registry; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -135,7 +141,11 @@ public interface ClientHelper { * @param item the item to find * @return the mod name */ - String getModFromItem(Item item); + default String getModFromItem(Item item) { + if (item.equals(Items.AIR)) + return ""; + return getModFromIdentifier(Registry.ITEM.getKey(item)); + } /** * Tries to delete the player's cursor item @@ -148,7 +158,12 @@ public interface ClientHelper { * @param item the item to find * @return the mod name with blue and italic formatting */ - Component getFormattedModFromItem(Item item); + default Component getFormattedModFromItem(Item item) { + String mod = getModFromItem(item); + if (mod.isEmpty()) + return NarratorChatListener.NO_TITLE; + return new TextComponent(mod).withStyle(ChatFormatting.BLUE, ChatFormatting.ITALIC); + } /** * Gets the formatted mod from an identifier @@ -156,7 +171,38 @@ public interface ClientHelper { * @param identifier the identifier to find * @return the mod name with blue and italic formatting */ - Component getFormattedModFromIdentifier(ResourceLocation identifier); + default Component getFormattedModFromIdentifier(ResourceLocation identifier) { + String mod = getModFromIdentifier(identifier); + if (mod.isEmpty()) + return NarratorChatListener.NO_TITLE; + return new TextComponent(mod).withStyle(ChatFormatting.BLUE, ChatFormatting.ITALIC); + } + + /** + * Gets the mod from a modid + * + * @param modid the modid of the mod + * @return the mod name with blue and italic formatting + */ + default Component getFormattedModFromModId(String modid) { + String mod = getModFromModId(modid); + if (mod.isEmpty()) + return NarratorChatListener.NO_TITLE; + return new TextComponent(mod).withStyle(ChatFormatting.BLUE, ChatFormatting.ITALIC); + } + + default List appendModIdToTooltips(List components, String modId) { + final String modName = ClientHelper.getInstance().getModFromModId(modId); + boolean alreadyHasMod = false; + for (Component s : components) + if (FormattingUtils.stripFormatting(s.getString()).equalsIgnoreCase(modName)) { + alreadyHasMod = true; + break; + } + if (!alreadyHasMod) + components.add(ClientHelper.getInstance().getFormattedModFromModId(modId)); + return components; + } /** * Gets the mod from an identifier diff --git a/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/DisplayHelper.java b/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/DisplayHelper.java index 517597f8e..cdafd0ba2 100644 --- a/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/DisplayHelper.java +++ b/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/DisplayHelper.java @@ -36,8 +36,6 @@ import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.function.Supplier; -import static net.minecraft.world.InteractionResult.PASS; - @Environment(EnvType.CLIENT) public interface DisplayHelper { @@ -167,15 +165,18 @@ public interface DisplayHelper { * @see BaseBoundsHandler#registerExclusionZones(Class, Supplier) for easier api */ default InteractionResult canItemSlotWidgetFit(int left, int top, T screen, Rectangle fullBounds) { - InteractionResult fit = isInZone(left, top); - if (fit == InteractionResult.FAIL) - return InteractionResult.FAIL; - InteractionResult fit2 = isInZone(left + 18, top + 18); - if (fit2 == InteractionResult.FAIL) - return InteractionResult.FAIL; - if (fit == InteractionResult.SUCCESS && fit2 == InteractionResult.SUCCESS) - return InteractionResult.SUCCESS; - return PASS; + InteractionResult fit; + fit = isInZone(left, top); + if (fit != InteractionResult.PASS) + return fit; + fit = isInZone(left + 18, top); + if (fit != InteractionResult.PASS) + return fit; + fit = isInZone(left, top + 18); + if (fit != InteractionResult.PASS) + return fit; + fit = isInZone(left + 18, top + 18); + return fit; } @Override diff --git a/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/TextRepresentable.java b/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/TextRepresentable.java index 96ca2c7af..b346ab822 100644 --- a/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/TextRepresentable.java +++ b/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/TextRepresentable.java @@ -26,10 +26,10 @@ package me.shedaniel.rei.api; import me.shedaniel.math.impl.PointHelper; import me.shedaniel.rei.api.widgets.Tooltip; import me.shedaniel.rei.utils.FormattingUtils; +import me.shedaniel.rei.utils.ImmutableLiteralText; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TextComponent; import org.jetbrains.annotations.NotNull; @Environment(EnvType.CLIENT) @@ -41,11 +41,11 @@ public interface TextRepresentable { if (tooltip != null && !tooltip.getText().isEmpty()) return tooltip.getText().get(0); } - return new TextComponent(""); + return ImmutableLiteralText.EMPTY; } @NotNull default Component asFormatStrippedText() { - return new TextComponent(FormattingUtils.stripFormatting(asFormattedText().getString())); + return new ImmutableLiteralText(FormattingUtils.stripFormatting(asFormattedText().getString())); } } diff --git a/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/widgets/Label.java b/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/widgets/Label.java index c22188634..55761012b 100644 --- a/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/widgets/Label.java +++ b/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/widgets/Label.java @@ -311,6 +311,8 @@ public abstract class Label extends WidgetWithBounds { public abstract void setMessage(@NotNull FormattedText message); + public abstract void setRainbow(boolean rainbow); + @NotNull public final Label text(@NotNull Component text) { setText(text); @@ -322,4 +324,10 @@ public abstract class Label extends WidgetWithBounds { setMessage(message); return this; } + + @NotNull + public final Label rainbow(boolean rainbow) { + setRainbow(rainbow); + return this; + } } diff --git a/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/utils/ImmutableLiteralText.java b/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/utils/ImmutableLiteralText.java index a13aa6dd6..0da3d19f8 100644 --- a/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/utils/ImmutableLiteralText.java +++ b/RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/utils/ImmutableLiteralText.java @@ -34,7 +34,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -public final class ImmutableLiteralText implements Component { +public final class ImmutableLiteralText implements MutableComponent { public static final ImmutableLiteralText EMPTY = new ImmutableLiteralText(""); private final String content; private FormattedCharSequence orderedText; @@ -60,7 +60,7 @@ public final class ImmutableLiteralText implements Component { @Override public MutableComponent plainCopy() { - return new TextComponent(content); + return this; } @Override @@ -85,4 +85,14 @@ public final class ImmutableLiteralText implements Component { } return orderedText; } + + @Override + public MutableComponent setStyle(Style style) { + return new TextComponent(content).withStyle(style); + } + + @Override + public MutableComponent append(Component component) { + return new TextComponent(content).append(component); + } } diff --git a/RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java b/RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java index 793052a28..0599b0dc1 100644 --- a/RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java +++ b/RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java @@ -32,6 +32,7 @@ import it.unimi.dsi.fastutil.objects.ReferenceSet; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.*; import me.shedaniel.rei.api.fluid.FluidSupportProvider; +import me.shedaniel.rei.api.fractions.Fraction; import me.shedaniel.rei.api.plugins.REIPluginV0; import me.shedaniel.rei.plugin.autocrafting.DefaultRecipeBookHandler; import me.shedaniel.rei.plugin.beacon.DefaultBeaconBaseCategory; @@ -403,7 +404,7 @@ public class DefaultPlugin implements REIPluginV0, BuiltinPlugin { FluidSupportProvider.getInstance().registerProvider(itemStack -> { Item item = itemStack.getItem(); if (item instanceof BucketItem) - return InteractionResultHolder.success(Stream.of(EntryStack.create(((BucketItem) item).content, 1000))); + return InteractionResultHolder.success(Stream.of(EntryStack.create(((BucketItem) item).content, Fraction.ofWhole(1)))); return InteractionResultHolder.pass(null); }); // SubsetsRegistry subsetsRegistry = SubsetsRegistry.INSTANCE; diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java index 1cb9b885f..a437bdfe1 100644 --- a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java @@ -74,7 +74,10 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.Set; @ApiStatus.Internal public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverlay { @@ -319,7 +322,7 @@ public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverl } subsetsButtonBounds = getSubsetsButtonBounds(); if (ConfigObject.getInstance().isSubsetsEnabled()) { - widgets.add(InternalWidgets.wrapLateRenderable(InternalWidgets.wrapTranslate(Widgets.createButton(subsetsButtonBounds, ((ClientHelperImpl) ClientHelper.getInstance()).isAprilFools.get() ? new TranslatableComponent("text.rei.tiny_potato") : new TranslatableComponent("text.rei.subsets")) + widgets.add(InternalWidgets.wrapLateRenderable(InternalWidgets.wrapTranslate(Widgets.createButton(subsetsButtonBounds, ClientHelperImpl.getInstance().isAprilFools.get() ? new TranslatableComponent("text.rei.tiny_potato") : new TranslatableComponent("text.rei.subsets")) .onClick(button -> { if (subsetsMenu == null) { wrappedSubsetsMenu = InternalWidgets.wrapTranslate(InternalWidgets.wrapLateRenderable(this.subsetsMenu = Menu.createSubsetsMenuFromRegistry(new Point(this.subsetsButtonBounds.x, this.subsetsButtonBounds.getMaxY()))), 0, 0, 400); @@ -338,7 +341,7 @@ public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverl }).tooltipLine(I18n.get("text.rei.go_back_first_page")).focusable(false).onRender((matrices, label) -> { label.setClickable(ENTRY_LIST_WIDGET.getTotalPages() > 1); label.setText(new TextComponent(String.format("%s/%s", ENTRY_LIST_WIDGET.getPage() + 1, Math.max(ENTRY_LIST_WIDGET.getTotalPages(), 1)))); - })); + }).rainbow(new Random().nextFloat() < 1.0E-4D || ClientHelperImpl.getInstance().isAprilFools.get())); } if (ConfigObject.getInstance().isCraftableFilterEnabled()) { Rectangle area = getCraftableToggleArea(); @@ -589,10 +592,10 @@ public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverl public void renderTooltipInner(PoseStack matrices, List lines, int mouseX, int mouseY) { if (lines.isEmpty()) return; - tooltipWidth = lines.stream().map(font::width).max(Integer::compareTo).get(); - tooltipHeight = lines.size() <= 1 ? 8 : lines.size() * 10; - tooltipLines = lines; - ScreenHelper.drawHoveringWidget(matrices, mouseX, mouseY, renderTooltipCallback, tooltipWidth, tooltipHeight, 0); + matrices.pushPose(); + matrices.translate(0, 0, 500); + minecraft.screen.renderTooltip(matrices, lines, mouseX, mouseY); + matrices.popPose(); } public void addTooltip(@Nullable Tooltip tooltip) { diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java index 02499b3e0..f0ba31ad2 100644 --- a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java @@ -327,17 +327,18 @@ public class FilteringScreen extends Screen { } public void updateEntriesPosition() { + int entrySize = entrySize(); this.innerBounds = updateInnerBounds(getBounds()); - int width = innerBounds.width / entrySize(); - int pageHeight = innerBounds.height / entrySize(); + int width = innerBounds.width / entrySize; + int pageHeight = innerBounds.height / entrySize; int slotsToPrepare = Math.max(entryStacks.size() * 3, width * pageHeight * 3); int currentX = 0; int currentY = 0; List entries = Lists.newArrayList(); for (int i = 0; i < slotsToPrepare; i++) { - int xPos = currentX * entrySize() + innerBounds.x; - int yPos = currentY * entrySize() + innerBounds.y; - entries.add(new EntryListEntry(xPos, yPos)); + int xPos = currentX * entrySize + innerBounds.x; + int yPos = currentY * entrySize + innerBounds.y; + entries.add(new EntryListEntry(xPos, yPos, entrySize)); currentX++; if (currentX >= width) { currentX = 0; @@ -453,10 +454,10 @@ public class FilteringScreen extends Screen { private boolean filtered = false; private boolean dirty = true; - private EntryListEntry(int x, int y) { + private EntryListEntry(int x, int y, int entrySize) { super(new Point(x, y)); this.backupY = y; - getBounds().width = getBounds().height = entrySize(); + getBounds().width = getBounds().height = entrySize; interactableFavorites(false); interactable(false); noHighlight(); diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/credits/CreditsEntryListWidget.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/credits/CreditsEntryListWidget.java index a2eebcd7f..da188dbd8 100644 --- a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/credits/CreditsEntryListWidget.java +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/credits/CreditsEntryListWidget.java @@ -25,12 +25,20 @@ package me.shedaniel.rei.gui.credits; import com.mojang.blaze3d.vertex.PoseStack; import me.shedaniel.clothconfig2.gui.widget.DynamicNewSmoothScrollingEntryListWidget; +import me.shedaniel.rei.impl.TextTransformations; +import net.minecraft.ChatFormatting; +import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiComponent; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.sounds.SoundEvents; import net.minecraft.util.FormattedCharSequence; import org.jetbrains.annotations.ApiStatus; +import java.net.URI; +import java.net.URISyntaxException; import java.util.List; @ApiStatus.Internal @@ -139,4 +147,66 @@ public class CreditsEntryListWidget extends DynamicNewSmoothScrollingEntryListWi } } + public static class LinkItem extends CreditsItem { + private Component text; + private List textSplit; + private String link; + private boolean contains; + private boolean rainbow; + + public LinkItem(Component text, String link, int width, boolean rainbow) { + this.text = text; + this.textSplit = Minecraft.getInstance().font.split(text, width); + this.link = link; + this.rainbow = rainbow; + } + + @Override + public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isSelected, float delta) { + contains = mouseX >= x && mouseX <= x + entryWidth && mouseY >= y && mouseY <= y + entryHeight; + if (contains) { + Minecraft.getInstance().screen.renderTooltip(matrices, new TextComponent("Click to open link."), mouseX, mouseY); + int yy = y; + for (FormattedCharSequence textSp : textSplit) { + FormattedCharSequence underlined = characterVisitor -> { + return textSp.accept((charIndex, style, codePoint) -> characterVisitor.accept(charIndex, style.applyFormat(ChatFormatting.UNDERLINE), codePoint)); + }; + if (rainbow) underlined = TextTransformations.applyRainbow(underlined, x + 5, yy); + Minecraft.getInstance().font.drawShadow(matrices, underlined, x + 5, yy, 0xff1fc3ff); + yy += 12; + } + } else { + int yy = y; + for (FormattedCharSequence textSp : textSplit) { + if (rainbow) textSp = TextTransformations.applyRainbow(textSp, x + 5, yy); + Minecraft.getInstance().font.drawShadow(matrices, textSp, x + 5, yy, 0xff1fc3ff); + yy += 12; + } + } + } + + @Override + public int getItemHeight() { + return 12 * textSplit.size(); + } + + @Override + public boolean changeFocus(boolean boolean_1) { + return false; + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (contains && button == 0) { + Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + try { + Util.getPlatform().openUri(new URI(link)); + return true; + } catch (URISyntaxException e) { + e.printStackTrace(); + } + } + return false; + } + } } diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/credits/CreditsScreen.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/credits/CreditsScreen.java index 8d62d4bc4..acded0329 100644 --- a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/credits/CreditsScreen.java +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/credits/CreditsScreen.java @@ -31,6 +31,7 @@ import me.shedaniel.rei.impl.ScreenHelper; import me.shedaniel.rei.utils.ImmutableLiteralText; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.metadata.CustomValue; +import net.minecraft.client.gui.GuiComponent; import net.minecraft.client.gui.chat.NarratorChatListener; import net.minecraft.client.gui.components.AbstractButton; import net.minecraft.client.gui.screens.Screen; @@ -112,6 +113,10 @@ public class CreditsScreen extends Screen { } } else entryListWidget.creditsAddEntry(new TextCreditsItem(new ImmutableLiteralText(line))); entryListWidget.creditsAddEntry(new TextCreditsItem(NarratorChatListener.NO_TITLE)); + entryListWidget.creditsAddEntry(new CreditsEntryListWidget.LinkItem(new ImmutableLiteralText("Visit the project at GitHub."), "https://www.github.com/shedaniel/RoughlyEnoughItems", entryListWidget.getItemWidth(), false)); + entryListWidget.creditsAddEntry(new CreditsEntryListWidget.LinkItem(new ImmutableLiteralText("Visit the project page at CurseForge."), "https://www.curseforge.com/minecraft/mc-mods/roughly-enough-items", entryListWidget.getItemWidth(), false)); + entryListWidget.creditsAddEntry(new CreditsEntryListWidget.LinkItem(new ImmutableLiteralText("Support the project via Patreon!"), "https://patreon.com/shedaniel", entryListWidget.getItemWidth(), true)); + entryListWidget.creditsAddEntry(new TextCreditsItem(NarratorChatListener.NO_TITLE)); children.add(buttonDone = new AbstractButton(width / 2 - 100, height - 26, 200, 20, new TranslatableComponent("gui.done")) { @Override public void onPress() { @@ -133,7 +138,7 @@ public class CreditsScreen extends Screen { public void render(PoseStack matrices, int int_1, int int_2, float float_1) { this.renderDirtBackground(0); this.entryListWidget.render(matrices, int_1, int_2, float_1); - this.drawCenteredString(matrices, this.font, I18n.get("text.rei.credits"), this.width / 2, 16, 16777215); + drawCenteredString(matrices, this.font, I18n.get("text.rei.credits"), this.width / 2, 16, 16777215); super.render(matrices, int_1, int_2, float_1); buttonDone.render(matrices, int_1, int_2, float_1); } diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/plugin/DefaultRuntimePlugin.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/plugin/DefaultRuntimePlugin.java index ca940c704..9f3ff4995 100644 --- a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/plugin/DefaultRuntimePlugin.java +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/plugin/DefaultRuntimePlugin.java @@ -68,12 +68,12 @@ public class DefaultRuntimePlugin implements REIPluginV0 { @Override public boolean isEmpty() { - return !((ClientHelperImpl) ClientHelper.getInstance()).isAprilFools.get(); + return !ClientHelperImpl.getInstance().isAprilFools.get(); } @Override public @Nullable Tooltip getTooltip(Point point) { - return Tooltip.create(new TextComponent("Kibby")); + return Tooltip.create(new TextComponent("Kirby"), ClientHelper.getInstance().getFormattedModFromModId("Dream Land")); } }); } diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListEntryWidget.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListEntryWidget.java index 9ab35d8f0..f01e16d37 100644 --- a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListEntryWidget.java +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListEntryWidget.java @@ -31,15 +31,13 @@ import me.shedaniel.rei.api.EntryStack; import net.minecraft.client.gui.screens.Screen; import net.minecraft.world.item.Item; -import static me.shedaniel.rei.gui.widget.EntryListWidget.entrySize; - public class EntryListEntryWidget extends EntryWidget { public int backupY; - protected EntryListEntryWidget(Point point) { + protected EntryListEntryWidget(Point point, int entrySize) { super(point); this.backupY = point.y; - getBounds().width = getBounds().height = entrySize(); + getBounds().width = getBounds().height = entrySize; } @Override diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java index eea8a5e30..3142f4517 100644 --- a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java @@ -112,31 +112,42 @@ public class EntryListWidget extends WidgetWithBounds { return Mth.ceil(SIZE * ConfigObject.getInstance().getEntrySize()); } - static boolean notSteppingOnExclusionZones(int left, int top, Rectangle listArea) { + static boolean notSteppingOnExclusionZones(int left, int top, int width, int height, Rectangle listArea) { Minecraft instance = Minecraft.getInstance(); for (OverlayDecider decider : DisplayHelper.getInstance().getSortedOverlayDeciders(instance.screen.getClass())) { - InteractionResult fit = decider.isInZone(left, top); - if (fit == InteractionResult.FAIL) - return false; - InteractionResult fit2 = decider.isInZone(left + 18, top + 18); - if (fit2 == InteractionResult.FAIL) - return false; - if (fit == InteractionResult.SUCCESS && fit2 == InteractionResult.SUCCESS) - return true; + InteractionResult fit = canItemSlotWidgetFit(left, top, width, height, decider); + if (fit != InteractionResult.PASS) + return fit == InteractionResult.SUCCESS; } return true; } + private static InteractionResult canItemSlotWidgetFit(int left, int top, int width, int height, OverlayDecider decider) { + InteractionResult fit; + fit = decider.isInZone(left, top); + if (fit != InteractionResult.PASS) + return fit; + fit = decider.isInZone(left + width, top); + if (fit != InteractionResult.PASS) + return fit; + fit = decider.isInZone(left, top + height); + if (fit != InteractionResult.PASS) + return fit; + fit = decider.isInZone(left + width, top + height); + return fit; + } + private static Rectangle updateInnerBounds(Rectangle bounds) { + int entrySize = entrySize(); if (ConfigObject.getInstance().isEntryListWidgetScrolled()) { - int width = Math.max(Mth.floor((bounds.width - 2 - 6) / (float) entrySize()), 1); + int width = Math.max(Mth.floor((bounds.width - 2 - 6) / (float) entrySize), 1); if (ConfigObject.getInstance().isLeftHandSidePanel()) - return new Rectangle((int) (bounds.getCenterX() - width * (entrySize() / 2f) + 3), bounds.y, width * entrySize(), bounds.height); - return new Rectangle((int) (bounds.getCenterX() - width * (entrySize() / 2f) - 3), bounds.y, width * entrySize(), bounds.height); + return new Rectangle((int) (bounds.getCenterX() - width * (entrySize / 2f) + 3), bounds.y, width * entrySize, bounds.height); + return new Rectangle((int) (bounds.getCenterX() - width * (entrySize / 2f) - 3), bounds.y, width * entrySize, bounds.height); } - int width = Math.max(Mth.floor((bounds.width - 2) / (float) entrySize()), 1); - int height = Math.max(Mth.floor((bounds.height - 2) / (float) entrySize()), 1); - return new Rectangle((int) (bounds.getCenterX() - width * (entrySize() / 2f)), (int) (bounds.getCenterY() - height * (entrySize() / 2f)), width * entrySize(), height * entrySize()); + int width = Math.max(Mth.floor((bounds.width - 2) / (float) entrySize), 1); + int height = Math.max(Mth.floor((bounds.height - 2) / (float) entrySize), 1); + return new Rectangle((int) (bounds.getCenterX() - width * (entrySize / 2f)), (int) (bounds.getCenterY() - height * (entrySize / 2f)), width * entrySize, height * entrySize); } @Override @@ -234,9 +245,11 @@ public class EntryListWidget extends WidgetWithBounds { blockedCount = 0; Stream entryStream = this.entries.stream().skip(nextIndex).filter(entry -> { - entry.getBounds().y = (int) (entry.backupY - scrolling.scrollAmount); - if (entry.getBounds().y > bounds.getMaxY()) return false; - if (notSteppingOnExclusionZones(entry.getBounds().x, entry.getBounds().y, innerBounds)) { + Rectangle entryBounds = entry.getBounds(); + + entryBounds.y = (int) (entry.backupY - scrolling.scrollAmount); + if (entryBounds.y > this.bounds.getMaxY()) return false; + if (notSteppingOnExclusionZones(entryBounds.x, entryBounds.y, entryBounds.width, entryBounds.height, innerBounds)) { EntryStack stack = allStacks.get(i[0]++); if (!stack.isEmpty()) { entry.entry(stack); @@ -368,17 +381,20 @@ public class EntryListWidget extends WidgetWithBounds { } public void updateEntriesPosition() { + int entrySize = entrySize(); this.innerBounds = updateInnerBounds(bounds); if (!ConfigObject.getInstance().isEntryListWidgetScrolled()) { this.renders = Lists.newArrayList(); page = Math.max(page, 0); List entries = Lists.newArrayList(); - int width = innerBounds.width / entrySize(); - int height = innerBounds.height / entrySize(); + int width = innerBounds.width / entrySize; + int height = innerBounds.height / entrySize; for (int currentY = 0; currentY < height; currentY++) { for (int currentX = 0; currentX < width; currentX++) { - if (notSteppingOnExclusionZones(currentX * entrySize() + innerBounds.x, currentY * entrySize() + innerBounds.y, innerBounds)) { - entries.add((EntryListEntry) new EntryListEntry(currentX * entrySize() + innerBounds.x, currentY * entrySize() + innerBounds.y).noBackground()); + int slotX = currentX * entrySize + innerBounds.x; + int slotY = currentY * entrySize + innerBounds.y; + if (notSteppingOnExclusionZones(slotX - 1, slotY - 1, entrySize, entrySize, innerBounds)) { + entries.add((EntryListEntry) new EntryListEntry(slotX, slotY, entrySize).noBackground()); } } } @@ -393,16 +409,16 @@ public class EntryListWidget extends WidgetWithBounds { this.widgets.addAll(entries); } else { page = 0; - int width = innerBounds.width / entrySize(); - int pageHeight = innerBounds.height / entrySize(); + int width = innerBounds.width / entrySize; + int pageHeight = innerBounds.height / entrySize; int slotsToPrepare = Math.max(allStacks.size() * 3, width * pageHeight * 3); int currentX = 0; int currentY = 0; List entries = Lists.newArrayList(); for (int i = 0; i < slotsToPrepare; i++) { - int xPos = currentX * entrySize() + innerBounds.x; - int yPos = currentY * entrySize() + innerBounds.y; - entries.add((EntryListEntry) new EntryListEntry(xPos, yPos).noBackground()); + int xPos = currentX * entrySize + innerBounds.x; + int yPos = currentY * entrySize + innerBounds.y; + entries.add((EntryListEntry) new EntryListEntry(xPos, yPos, entrySize).noBackground()); currentX++; if (currentX >= width) { currentX = 0; @@ -531,8 +547,8 @@ public class EntryListWidget extends WidgetWithBounds { } private class EntryListEntry extends EntryListEntryWidget { - private EntryListEntry(int x, int y) { - super(new Point(x, y)); + private EntryListEntry(int x, int y, int entrySize) { + super(new Point(x, y), entrySize); } @Override diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/FavoritesListWidget.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/FavoritesListWidget.java index cb9171296..a27adc88d 100644 --- a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/FavoritesListWidget.java +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/FavoritesListWidget.java @@ -84,10 +84,11 @@ public class FavoritesListWidget extends WidgetWithBounds { private boolean draggingScrollBar = false; private static Rectangle updateInnerBounds(Rectangle bounds) { - int width = Math.max(Mth.floor((bounds.width - 2 - 6) / (float) entrySize()), 1); + int entrySize = entrySize(); + int width = Math.max(Mth.floor((bounds.width - 2 - 6) / (float) entrySize), 1); if (!ConfigObject.getInstance().isLeftHandSidePanel()) - return new Rectangle((int) (bounds.getCenterX() - width * (entrySize() / 2f) + 3), bounds.y, width * entrySize(), bounds.height); - return new Rectangle((int) (bounds.getCenterX() - width * (entrySize() / 2f) - 3), bounds.y, width * entrySize(), bounds.height); + return new Rectangle((int) (bounds.getCenterX() - width * (entrySize / 2f) + 3), bounds.y, width * entrySize, bounds.height); + return new Rectangle((int) (bounds.getCenterX() - width * (entrySize / 2f) - 3), bounds.y, width * entrySize, bounds.height); } @Override @@ -119,9 +120,11 @@ public class FavoritesListWidget extends WidgetWithBounds { blockedCount = 0; Stream entryStream = this.entries.stream().skip(nextIndex).filter(entry -> { - entry.getBounds().y = (int) (entry.backupY - scrolling.scrollAmount); - if (entry.getBounds().y > bounds.getMaxY()) return false; - if (notSteppingOnExclusionZones(entry.getBounds().x, entry.getBounds().y, innerBounds)) { + Rectangle entryBounds = entry.getBounds(); + + entryBounds.y = (int) (entry.backupY - scrolling.scrollAmount); + if (entryBounds.y > this.bounds.getMaxY()) return false; + if (notSteppingOnExclusionZones(entryBounds.x, entryBounds.y, entryBounds.width, entryBounds.height, innerBounds)) { EntryStack stack = favorites.get(i[0]++); if (!stack.isEmpty()) { entry.entry(stack); @@ -242,17 +245,18 @@ public class FavoritesListWidget extends WidgetWithBounds { } public void updateEntriesPosition() { + int entrySize = entrySize(); this.innerBounds = updateInnerBounds(bounds); - int width = innerBounds.width / entrySize(); - int pageHeight = innerBounds.height / entrySize(); + int width = innerBounds.width / entrySize; + int pageHeight = innerBounds.height / entrySize; int slotsToPrepare = Math.max(favorites.size() * 3, width * pageHeight * 3); int currentX = 0; int currentY = 0; List entries = Lists.newArrayList(); for (int i = 0; i < slotsToPrepare; i++) { - int xPos = currentX * entrySize() + innerBounds.x; - int yPos = currentY * entrySize() + innerBounds.y; - entries.add((EntryListEntry) new EntryListEntry(xPos, yPos).noBackground()); + int xPos = currentX * entrySize + innerBounds.x; + int yPos = currentY * entrySize + innerBounds.y; + entries.add((EntryListEntry) new EntryListEntry(xPos, yPos, entrySize).noBackground()); currentX++; if (currentX >= width) { currentX = 0; @@ -295,8 +299,8 @@ public class FavoritesListWidget extends WidgetWithBounds { } private class EntryListEntry extends EntryListEntryWidget { - private EntryListEntry(int x, int y) { - super(new Point(x, y)); + private EntryListEntry(int x, int y, int entrySize) { + super(new Point(x, y), entrySize); } @Override diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java index b07898abe..50da7c39e 100644 --- a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java @@ -40,24 +40,17 @@ import net.fabricmc.fabric.api.network.ClientSidePacketRegistry; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; import net.fabricmc.loader.api.metadata.ModMetadata; -import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.chat.NarratorChatListener; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; -import net.minecraft.core.Registry; import net.minecraft.network.FriendlyByteBuf; -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.util.LazyLoadedValue; import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -66,7 +59,6 @@ import java.time.LocalDateTime; import java.util.*; import java.util.function.Supplier; import java.util.stream.Collectors; -import java.util.stream.Stream; import static me.shedaniel.rei.impl.Internals.attachInstance; @@ -102,29 +94,6 @@ public class ClientHelperImpl implements ClientHelper, ClientModInitializer { return instance; } - @Override - public Component getFormattedModFromItem(Item item) { - String mod = getModFromItem(item); - if (mod.isEmpty()) - return NarratorChatListener.NO_TITLE; - return new TextComponent(mod).withStyle(ChatFormatting.BLUE, ChatFormatting.ITALIC); - } - - @Override - public Component getFormattedModFromIdentifier(ResourceLocation identifier) { - String mod = getModFromIdentifier(identifier); - if (mod.isEmpty()) - return NarratorChatListener.NO_TITLE; - return new TextComponent(mod).withStyle(ChatFormatting.BLUE, ChatFormatting.ITALIC); - } - - @Override - public String getModFromItem(Item item) { - if (item.equals(Items.AIR)) - return ""; - return getModFromIdentifier(Registry.ITEM.getKey(item)); - } - @Override public String getModFromModId(String modid) { if (modid == null) @@ -296,7 +265,8 @@ public class ClientHelperImpl implements ClientHelper, ClientModInitializer { @Nullable private ResourceLocation preferredOpenedCategory = null; @Nullable private EntryStack inputNotice; @Nullable private EntryStack outputNotice; - @NotNull private final LazyLoadedValue, List>> map = new LazyLoadedValue<>(() -> RecipeHelper.getInstance().buildMapFor(this)); + @NotNull + private final LazyLoadedValue, List>> map = new LazyLoadedValue<>(() -> RecipeHelper.getInstance().buildMapFor(this)); @Override public ClientHelper.ViewSearchBuilder addCategory(ResourceLocation category) { diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java index 1037f6ac4..0be9b9e12 100644 --- a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java @@ -382,7 +382,7 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { } public static class Appearance { - @UseSpecialRecipeTypeScreen private RecipeScreenType recipeScreenType = RecipeScreenType.UNSET; + @UseSpecialRecipeTypeScreen private RecipeScreenType recipeScreenType = RecipeScreenType.ORIGINAL; @Comment("Declares the appearance of REI windows.") @ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON) private AppearanceTheme theme = AppearanceTheme.LIGHT; @ConfigEntry.Gui.CollapsibleObject(startExpanded = true) diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/FluidEntryStack.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/FluidEntryStack.java index 2d777869e..d114b46a5 100644 --- a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/FluidEntryStack.java +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/FluidEntryStack.java @@ -38,8 +38,8 @@ import me.shedaniel.rei.api.EntryStack; import me.shedaniel.rei.api.fractions.Fraction; import me.shedaniel.rei.api.widgets.Tooltip; import me.shedaniel.rei.utils.CollectionUtils; -import me.shedaniel.rei.utils.FormattingUtils; import me.shedaniel.rei.utils.ImmutableLiteralText; +import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -200,18 +200,12 @@ public class FluidEntryStack extends AbstractEntryStack { if (amountTooltip != null) toolTip.addAll(Stream.of(amountTooltip.split("\n")).map(TextComponent::new).collect(Collectors.toList())); } + if (Minecraft.getInstance().options.advancedItemTooltips) { + toolTip.add((new TextComponent(Registry.FLUID.getKey(this.getFluid()).toString())).withStyle(ChatFormatting.DARK_GRAY)); + } toolTip.addAll(get(Settings.TOOLTIP_APPEND_EXTRA).apply(this)); if (get(Settings.TOOLTIP_APPEND_MOD).get() && ConfigObject.getInstance().shouldAppendModNames()) { - ResourceLocation id = Registry.FLUID.getKey(fluid); - final String modId = ClientHelper.getInstance().getModFromIdentifier(id); - boolean alreadyHasMod = false; - for (Component s : toolTip) - if (FormattingUtils.stripFormatting(s.getString()).equalsIgnoreCase(modId)) { - alreadyHasMod = true; - break; - } - if (!alreadyHasMod) - toolTip.add(ClientHelper.getInstance().getFormattedModFromIdentifier(id)); + ClientHelper.getInstance().appendModIdToTooltips(toolTip, Registry.FLUID.getKey(getFluid()).getNamespace()); } return Tooltip.create(toolTip); } diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/InternalWidgets.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/InternalWidgets.java index 6bb997af7..9256367e0 100644 --- a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/InternalWidgets.java +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/InternalWidgets.java @@ -145,7 +145,7 @@ public final class InternalWidgets { .tooltipSupplier(button -> { String str = ""; if (errorTooltip[0] == null) { - if (((ClientHelperImpl) ClientHelper.getInstance()).isYog.get()) + if (ClientHelperImpl.getInstance().isYog.get()) str += I18n.get("text.auto_craft.move_items.yog"); else str += I18n.get("text.auto_craft.move_items"); diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ItemEntryStack.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ItemEntryStack.java index f59746214..cc471494e 100644 --- a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ItemEntryStack.java +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ItemEntryStack.java @@ -38,7 +38,6 @@ import me.shedaniel.rei.api.ConfigObject; import me.shedaniel.rei.api.EntryStack; import me.shedaniel.rei.api.fractions.Fraction; import me.shedaniel.rei.api.widgets.Tooltip; -import me.shedaniel.rei.utils.FormattingUtils; import me.shedaniel.rei.utils.ImmutableLiteralText; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; @@ -290,15 +289,7 @@ public class ItemEntryStack extends AbstractEntryStack implements OptimalEntrySt List toolTip = tryGetItemStackToolTip(true); toolTip.addAll(get(Settings.TOOLTIP_APPEND_EXTRA).apply(this)); if (get(Settings.TOOLTIP_APPEND_MOD).get() && ConfigObject.getInstance().shouldAppendModNames()) { - final String modId = ClientHelper.getInstance().getModFromItem(getItem()); - boolean alreadyHasMod = false; - for (Component s : toolTip) - if (FormattingUtils.stripFormatting(s.getString()).equalsIgnoreCase(modId)) { - alreadyHasMod = true; - break; - } - if (!alreadyHasMod) - toolTip.add(ClientHelper.getInstance().getFormattedModFromItem(getItem())); + ClientHelper.getInstance().appendModIdToTooltips(toolTip, Registry.ITEM.getKey(getItem()).getNamespace()); } return Tooltip.create(toolTip); } diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/TextTransformations.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/TextTransformations.java new file mode 100644 index 000000000..cb812f5af --- /dev/null +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/TextTransformations.java @@ -0,0 +1,21 @@ +package me.shedaniel.rei.impl; + +import me.shedaniel.math.Color; +import net.minecraft.Util; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.TextColor; +import net.minecraft.util.FormattedCharSequence; +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Internal +public class TextTransformations { + public static FormattedCharSequence applyRainbow(FormattedCharSequence sequence, int x, int y) { + int[] combinedX = {x}; + return sink -> sequence.accept((charIndex, style, codePoint) -> { + if (charIndex == 0) combinedX[0] = x; + int rgb = Color.HSBtoRGB(((Util.getMillis() - combinedX[0] * 10 - y * 10) % 2000) / 2000F, 0.8F, 0.95F); + combinedX[0] += Minecraft.getInstance().font.getSplitter().widthProvider.getWidth(codePoint, style); + return sink.accept(charIndex, style.withColor(TextColor.fromRgb(rgb)), codePoint); + }); + } +} diff --git a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/widgets/LabelWidget.java b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/widgets/LabelWidget.java index 0f73fab78..d867d9826 100644 --- a/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/widgets/LabelWidget.java +++ b/RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/widgets/LabelWidget.java @@ -31,6 +31,7 @@ import me.shedaniel.rei.api.REIHelper; import me.shedaniel.rei.api.widgets.Label; import me.shedaniel.rei.api.widgets.Tooltip; import me.shedaniel.rei.api.widgets.Widgets; +import me.shedaniel.rei.impl.TextTransformations; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.locale.Language; import net.minecraft.network.chat.FormattedText; @@ -62,6 +63,7 @@ public final class LabelWidget extends Label { @Nullable private Consumer