diff options
| author | Kevin <92656833+kevinthegreat1@users.noreply.github.com> | 2024-12-29 20:18:47 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-12-30 09:18:47 +0800 |
| commit | 145ba0948b03f10b6720fc87e0eecd7c8c5538a4 (patch) | |
| tree | f1e37aaec08c9586cee86f3c4d6341691dde2262 /src/main/java | |
| parent | 4434668d70d7c63b176a811c2f710c0bcae1db87 (diff) | |
| download | Skyblocker-145ba0948b03f10b6720fc87e0eecd7c8c5538a4.tar.gz Skyblocker-145ba0948b03f10b6720fc87e0eecd7c8c5538a4.tar.bz2 Skyblocker-145ba0948b03f10b6720fc87e0eecd7c8c5538a4.zip | |
Title hud refactor (#951)
* Refactor TitleContainer and fix bugs
* Sync with hud refactor
* Update translatable key checks
* TABS
* Remove extra renderBackground
* Add EnumUtils
* Migrate to EnumUtils
Diffstat (limited to 'src/main/java')
11 files changed, 487 insertions, 503 deletions
diff --git a/src/main/java/de/hysky/skyblocker/config/HudConfigScreen.java b/src/main/java/de/hysky/skyblocker/config/HudConfigScreen.java index ac1d8966..06bec737 100644 --- a/src/main/java/de/hysky/skyblocker/config/HudConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/config/HudConfigScreen.java @@ -1,7 +1,7 @@ package de.hysky.skyblocker.config; -import de.hysky.skyblocker.skyblock.tabhud.widget.HudWidget; import de.hysky.skyblocker.utils.render.RenderHelper; +import de.hysky.skyblocker.utils.render.gui.AbstractWidget; import it.unimi.dsi.fastutil.ints.IntIntMutablePair; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; @@ -13,129 +13,140 @@ import java.util.List; /** * A screen for configuring the positions of HUD widgets. * <p> + * Note: This is currently only used for title container. There is a new system for other HUD widgets, see {@link de.hysky.skyblocker.skyblock.tabhud.config.WidgetsConfigurationScreen} + * <p> * This class takes care of rendering the widgets, dragging them, and resetting their positions. * Create one subclass for each collection of HUD widgets that are displayed at the same time. * (i.e. one for dwarven mines, one for the end, etc.) See an implementation for an example. */ public abstract class HudConfigScreen extends Screen { - private final Screen parent; - private final List<HudWidget> widgets; - - private HudWidget draggingWidget; - private double mouseClickRelativeX; - private double mouseClickRelativeY; - - /** - * Creates a new HudConfigScreen with the passed title, parent, and widget - * @param title the title of the screen - * @param parent the parent screen - * @param widget the widget to configure - */ - public HudConfigScreen(Text title, Screen parent, HudWidget widget) { - this(title, parent, List.of(widget)); - } - - /** - * Creates a new HudConfigScreen with the passed title, parent, and widgets - * @param title the title of the screen - * @param parent the parent screen - * @param widgets the widgets to configure - */ - public HudConfigScreen(Text title, Screen parent, List<HudWidget> widgets) { - super(title); - this.parent = parent; - this.widgets = widgets; - resetPos(); - } - - @Override - public final void render(DrawContext context, int mouseX, int mouseY, float delta) { - super.render(context, mouseX, mouseY, delta); - renderWidget(context, widgets); - context.drawCenteredTextWithShadow(textRenderer, "Right Click To Reset Position", width / 2, height / 2, Color.GRAY.getRGB()); - } - - /** - * Renders the widgets using the default {@link HudWidget#render(DrawContext)} method. Override to change the behavior. - * @param context the context to render in - * @param widgets the widgets to render - */ - protected void renderWidget(DrawContext context, List<HudWidget> widgets) { - for (HudWidget widget : widgets) { - widget.render(context); - } - } - - @Override - public final boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - if (button == 0 && draggingWidget != null) { - draggingWidget.setX((int) Math.clamp(mouseX - mouseClickRelativeX, 0, this.width - draggingWidget.getWidth())); - draggingWidget.setY((int) Math.clamp(mouseY - mouseClickRelativeY, 0, this.height - draggingWidget.getHeight())); - } - return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); - } - - @Override - public final boolean mouseClicked(double mouseX, double mouseY, int button) { - if (button == 0) { - for (HudWidget widget : widgets) { - if (RenderHelper.pointIsInArea(mouseX, mouseY, widget.getX(), widget.getY(), widget.getX() + widget.getWidth(), widget.getY() + widget.getHeight())) { - draggingWidget = widget; - mouseClickRelativeX = mouseX - widget.getX(); - mouseClickRelativeY = mouseY - widget.getY(); - break; - } - } - } else if (button == 1) { - resetPos(); - } - return super.mouseClicked(mouseX, mouseY, button); - } - - @Override - public final boolean mouseReleased(double mouseX, double mouseY, int button) { - draggingWidget = null; - return super.mouseReleased(mouseX, mouseY, button); - } - - /** - * Resets the positions of the widgets to the positions in the config. Override to change the behavior. - */ - protected void resetPos() { - List<IntIntMutablePair> configPositions = getConfigPos(SkyblockerConfigManager.get()); - if (configPositions.size() != widgets.size()) { - throw new IllegalStateException("The number of positions (" + configPositions.size() + ") does not match the number of widgets (" + widgets.size() + ")"); - } - for (int i = 0; i < widgets.size(); i++) { - HudWidget widget = widgets.get(i); - IntIntMutablePair configPos = configPositions.get(i); - widget.setX(configPos.leftInt()); - widget.setY(configPos.rightInt()); - } - } - - /** - * Returns the positions of the widgets in the config - * @param config the config to get the positions from - * @return the positions of the widgets - */ - protected abstract List<IntIntMutablePair> getConfigPos(SkyblockerConfig config); - - @Override - public final void close() { - SkyblockerConfig skyblockerConfig = SkyblockerConfigManager.get(); - savePos(skyblockerConfig, widgets); - SkyblockerConfigManager.save(); - - client.setScreen(parent); - } - - /** - * Saves the passed positions to the config. - * <p> - * NOTE: The parent class will call {@link SkyblockerConfigManager#save()} right after this method - * @param configManager the config so you don't have to get it - * @param widgets the widgets to save - */ - protected abstract void savePos(SkyblockerConfig configManager, List<HudWidget> widgets); + protected final Screen parent; + protected final List<AbstractWidget> widgets; + + private AbstractWidget draggingWidget; + private double mouseClickRelativeX; + private double mouseClickRelativeY; + + /** + * Creates a new HudConfigScreen with the passed title, parent, and widget + * + * @param title the title of the screen + * @param parent the parent screen + * @param widget the widget to configure + */ + public HudConfigScreen(Text title, Screen parent, AbstractWidget widget) { + this(title, parent, List.of(widget)); + } + + /** + * Creates a new HudConfigScreen with the passed title, parent, and widgets + * + * @param title the title of the screen + * @param parent the parent screen + * @param widgets the widgets to configure + */ + public HudConfigScreen(Text title, Screen parent, List<AbstractWidget> widgets) { + super(title); + this.parent = parent; + this.widgets = widgets; + resetPos(); + } + + @Override + public final void render(DrawContext context, int mouseX, int mouseY, float delta) { + super.render(context, mouseX, mouseY, delta); + renderWidget(context, widgets, delta); + context.drawCenteredTextWithShadow(textRenderer, "Right Click To Reset Position", width / 2, height / 2, Color.GRAY.getRGB()); + } + + /** + * Renders the widgets using the default {@link AbstractWidget#render(DrawContext, int, int, float)} method. Override to change the behavior. + * + * @param context the context to render in + * @param widgets the widgets to render + */ + protected void renderWidget(DrawContext context, List<AbstractWidget> widgets, float delta) { + for (AbstractWidget widget : widgets) { + widget.render(context, -1, -1, delta); + } + } + + @Override + public final boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + if (button == 0 && draggingWidget != null) { + draggingWidget.setX((int) Math.clamp(mouseX - mouseClickRelativeX, 0, this.width - draggingWidget.getWidth()) - getWidgetXOffset(draggingWidget)); + draggingWidget.setY((int) Math.clamp(mouseY - mouseClickRelativeY, 0, this.height - draggingWidget.getHeight())); + } + return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + } + + @Override + public final boolean mouseClicked(double mouseX, double mouseY, int button) { + if (button == 0) { + for (AbstractWidget widget : widgets) { + if (RenderHelper.pointIsInArea(mouseX, mouseY, widget.getX() + getWidgetXOffset(widget), widget.getY(), widget.getX() + getWidgetXOffset(widget) + widget.getWidth(), widget.getY() + widget.getHeight())) { + draggingWidget = widget; + mouseClickRelativeX = mouseX - widget.getX() - getWidgetXOffset(widget); + mouseClickRelativeY = mouseY - widget.getY(); + break; + } + } + } else if (button == 1) { + resetPos(); + } + return super.mouseClicked(mouseX, mouseY, button); + } + + @Override + public final boolean mouseReleased(double mouseX, double mouseY, int button) { + draggingWidget = null; + return super.mouseReleased(mouseX, mouseY, button); + } + + protected int getWidgetXOffset(AbstractWidget widget) { + return 0; + } + + /** + * Resets the positions of the widgets to the positions in the config. Override to change the behavior. + */ + protected void resetPos() { + List<IntIntMutablePair> configPositions = getConfigPos(SkyblockerConfigManager.get()); + if (configPositions.size() != widgets.size()) { + throw new IllegalStateException("The number of positions (" + configPositions.size() + ") does not match the number of widgets (" + widgets.size() + ")"); + } + for (int i = 0; i < widgets.size(); i++) { + AbstractWidget widget = widgets.get(i); + IntIntMutablePair configPos = configPositions.get(i); + widget.setX(configPos.leftInt()); + widget.setY(configPos.rightInt()); + } + } + + /** + * Returns the positions of the widgets in the config + * + * @param config the config to get the positions from + * @return the positions of the widgets + */ + protected abstract List<IntIntMutablePair> getConfigPos(SkyblockerConfig config); + + @Override + public final void close() { + SkyblockerConfig skyblockerConfig = SkyblockerConfigManager.get(); + savePos(skyblockerConfig, widgets); + SkyblockerConfigManager.save(); + + client.setScreen(parent); + } + + /** + * Saves the passed positions to the config. + * <p> + * NOTE: The parent class will call {@link SkyblockerConfigManager#save()} right after this method + * + * @param configManager the config so you don't have to get it + * @param widgets the widgets to save + */ + protected abstract void savePos(SkyblockerConfig configManager, List<AbstractWidget> widgets); } diff --git a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java index 55ec5094..deb981a1 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java @@ -131,10 +131,14 @@ public class UIAndVisualsConfig { public int y = 10; @SerialEntry - public Direction direction = Direction.HORIZONTAL; + public Direction direction = Direction.VERTICAL; @SerialEntry public Alignment alignment = Alignment.MIDDLE; + + public float getRenderScale() { + return titleContainerScale * 0.03f; + } } public enum Direction { @@ -147,7 +151,7 @@ public class UIAndVisualsConfig { } public enum Alignment { - LEFT, RIGHT, MIDDLE; + LEFT, MIDDLE, RIGHT; @Override public String toString() { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapConfigScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapConfigScreen.java index 90f7ddc1..ee3f747a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapConfigScreen.java @@ -31,7 +31,6 @@ public class DungeonMapConfigScreen extends Screen { @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { super.render(context, mouseX, mouseY, delta); - renderBackground(context, mouseX, mouseY, delta); renderHUDMap(context, mapX, mapY); renderHUDScore(context, scoreX, scoreY); context.drawCenteredTextWithShadow(textRenderer, "Right Click To Reset Position", width >> 1, height >> 1, Color.GRAY.getRGB()); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarWidget.java index e3a94bcd..18c8905a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarWidget.java @@ -1,5 +1,6 @@ package de.hysky.skyblocker.skyblock.fancybars; +import de.hysky.skyblocker.utils.EnumUtils; import it.unimi.dsi.fastutil.booleans.BooleanConsumer; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; @@ -211,7 +212,7 @@ public class EditBarWidget extends ContainerWidget { @Override public void onClick(double mouseX, double mouseY) { - current = values[(current.ordinal() + 1) % values.length]; + current = EnumUtils.cycle(current); if (onChange != null) onChange.accept(current); super.onClick(mouseX, mouseY); } @@ -334,4 +335,4 @@ public class EditBarWidget extends ContainerWidget { protected double getDeltaYPerScroll() { return 0; } -}
\ No newline at end of file +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockItemRarity.java b/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockItemRarity.java index a5043e06..9008fb4e 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockItemRarity.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockItemRarity.java @@ -1,6 +1,7 @@ package de.hysky.skyblocker.skyblock.item; import com.mojang.serialization.Codec; +import de.hysky.skyblocker.utils.EnumUtils; import net.minecraft.util.Formatting; import net.minecraft.util.StringIdentifiable; @@ -41,6 +42,6 @@ public enum SkyblockItemRarity implements StringIdentifiable { } public SkyblockItemRarity next() { - return values()[(ordinal() + 1) % values().length]; + return EnumUtils.cycle(this); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/preview/PreviewTab.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/preview/PreviewTab.java index f72bc293..2cd743ac 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/preview/PreviewTab.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/preview/PreviewTab.java @@ -11,6 +11,7 @@ import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.pipeline.WidgetPosition import de.hysky.skyblocker.skyblock.tabhud.util.PlayerListMgr; import de.hysky.skyblocker.skyblock.tabhud.widget.HudWidget; import de.hysky.skyblocker.skyblock.tabhud.widget.TabHudWidget; +import de.hysky.skyblocker.utils.EnumUtils; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Location; import de.hysky.skyblocker.utils.render.gui.DropdownWidget; @@ -307,8 +308,7 @@ public class PreviewTab implements Tab { widgetOptions.addWidget(ButtonWidget.builder(Text.literal(ye), button -> { ScreenBuilder builder = ScreenMaster.getScreenBuilder(getCurrentLocation()); PositionRule rule = builder.getPositionRuleOrDefault(hudWidget.getInternalID()); - ScreenMaster.ScreenLayer[] values = ScreenMaster.ScreenLayer.values(); - ScreenMaster.ScreenLayer newLayer = values[(rule.screenLayer().ordinal() + 1) % values.length]; + ScreenMaster.ScreenLayer newLayer = EnumUtils.cycle(rule.screenLayer()); PositionRule newRule = new PositionRule( rule.parent(), diff --git a/src/main/java/de/hysky/skyblocker/utils/EnumUtils.java b/src/main/java/de/hysky/skyblocker/utils/EnumUtils.java new file mode 100644 index 00000000..ba1ad1d2 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/EnumUtils.java @@ -0,0 +1,13 @@ +package de.hysky.skyblocker.utils; + +public class EnumUtils { + public static <T extends Enum<T>> T cycle(T current) { + T[] values = current.getDeclaringClass().getEnumConstants(); + return values[(current.ordinal() + 1) % values.length]; + } + + public static <T extends Enum<T>> T cycleBackwards(T current) { + T[] values = current.getDeclaringClass().getEnumConstants(); + return values[(current.ordinal() - 1 + values.length) % values.length]; + } +} diff --git a/src/main/java/de/hysky/skyblocker/utils/render/gui/EmptyWidget.java b/src/main/java/de/hysky/skyblocker/utils/render/gui/EmptyWidget.java new file mode 100644 index 00000000..6d1324ec --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/render/gui/EmptyWidget.java @@ -0,0 +1,8 @@ +package de.hysky.skyblocker.utils.render.gui; + +import net.minecraft.client.gui.DrawContext; + +public class EmptyWidget extends AbstractWidget { + @Override + public void render(DrawContext context, int mouseX, int mouseY, float delta) {} +} diff --git a/src/main/java/de/hysky/skyblocker/utils/render/title/Title.java b/src/main/java/de/hysky/skyblocker/utils/render/title/Title.java index 890976ae..6b32da7d 100644 --- a/src/main/java/de/hysky/skyblocker/utils/render/title/Title.java +++ b/src/main/java/de/hysky/skyblocker/utils/render/title/Title.java @@ -1,5 +1,6 @@ package de.hysky.skyblocker.utils.render.title; +import com.demonwav.mcdev.annotations.Translatable; import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -10,46 +11,46 @@ import net.minecraft.util.Formatting; * @see TitleContainer */ public class Title { - private MutableText text; - protected float x = -1; - protected float y = -1; - - /** - * Constructs a new title with the given translation key and formatting to be applied. - * - * @param textKey the translation key - * @param formatting the formatting to be applied to the text - */ - public Title(String textKey, Formatting formatting) { - this(Text.translatable(textKey).formatted(formatting)); - } - - /** - * Constructs a new title with the given {@link MutableText}. - * Use {@link Text#literal(String)} or {@link Text#translatable(String)} to create a {@link MutableText} - * - * @param text the mutable text - */ - public Title(MutableText text) { - this.text = text; - } - - public MutableText getText() { - return text; - } - - public Title setText(MutableText text) { - this.text = text; - - return this; - } - - protected boolean isDefaultPos() { - return x == -1 && y == -1; - } - - protected void resetPos() { - this.x = -1; - this.y = -1; - } + private MutableText text; + protected float x = -1; + protected float y = -1; + + /** + * Constructs a new title with the given translation key and formatting to be applied. + * + * @param textKey the translation key + * @param formatting the formatting to be applied to the text + */ + public Title(@Translatable String textKey, Formatting formatting) { + this(Text.translatable(textKey).formatted(formatting)); + } + + /** + * Constructs a new title with the given {@link MutableText}. + * Use {@link Text#literal(String)} or {@link Text#translatable(String)} to create a {@link MutableText} + * + * @param text the mutable text + */ + public Title(MutableText text) { + this.text = text; + } + + public MutableText getText() { + return text; + } + + public Title setText(MutableText text) { + this.text = text; + + return this; + } + + protected boolean isDefaultPos() { + return x == -1 && y == -1; + } + + protected void resetPos() { + this.x = -1; + this.y = -1; + } } diff --git a/src/main/java/de/hysky/skyblocker/utils/render/title/TitleContainer.java b/src/main/java/de/hysky/skyblocker/utils/render/title/TitleContainer.java index c3d7faa4..83544976 100644 --- a/src/main/java/de/hysky/skyblocker/utils/render/title/TitleContainer.java +++ b/src/main/java/de/hysky/skyblocker/utils/render/title/TitleContainer.java @@ -17,162 +17,156 @@ import java.util.LinkedHashSet; import java.util.Set; public class TitleContainer { - /** - * The set of titles which will be rendered. - * - * @see #containsTitle(Title) - * @see #addTitle(Title) - * @see #addTitle(Title, int) - * @see #removeTitle(Title) - */ - private static final Set<Title> titles = new LinkedHashSet<>(); - - @Init - public static void init() { - HudRenderEvents.BEFORE_CHAT.register(TitleContainer::render); - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(ClientCommandManager.literal("skyblocker") - .then(ClientCommandManager.literal("hud") - .then(ClientCommandManager.literal("titleContainer") - .executes(Scheduler.queueOpenScreenCommand(TitleContainerConfigScreen::new)))))); - } - - /** - * Returns {@code true} if the title is currently shown. - * - * @param title the title to check - * @return whether the title in currently shown - */ - public static boolean containsTitle(Title title) { - return titles.contains(title); - } - - /** - * Adds a title to be shown - * - * @param title the title to be shown - * @return whether the title is already currently being shown - */ - public static boolean addTitle(Title title) { - if (titles.add(title)) { - title.resetPos(); - return true; - } - return false; - } - - /** - * Adds a title to be shown for a set number of ticks - * - * @param title the title to be shown - * @param ticks the number of ticks to show the title - * @return whether the title is already currently being shown - */ - public static boolean addTitle(Title title, int ticks) { - if (addTitle(title)) { - Scheduler.INSTANCE.schedule(() -> TitleContainer.removeTitle(title), ticks); - return true; - } - return false; - } - - /** - * Stops showing a title - * - * @param title the title to stop showing - */ - public static void removeTitle(Title title) { - titles.remove(title); - } - - private static void render(DrawContext context, RenderTickCounter tickCounter) { - render(context, titles, SkyblockerConfigManager.get().uiAndVisuals.titleContainer.x, SkyblockerConfigManager.get().uiAndVisuals.titleContainer.y, tickCounter.getTickDelta(true)); - } - - protected static void render(DrawContext context, Set<Title> titles, int xPos, int yPos, float tickDelta) { - var client = MinecraftClient.getInstance(); - TextRenderer textRenderer = client.textRenderer; - - // Calculate Scale to use - float scale = 3F * (SkyblockerConfigManager.get().uiAndVisuals.titleContainer.titleContainerScale / 100F); - - // Grab direction and alignment values - UIAndVisualsConfig.Direction direction = SkyblockerConfigManager.get().uiAndVisuals.titleContainer.direction; - UIAndVisualsConfig.Alignment alignment = SkyblockerConfigManager.get().uiAndVisuals.titleContainer.alignment; - // x/y refer to the starting position for the text - // y always starts at yPos - float x = 0; - float y = yPos; - - //Calculate the width of combined text - float width = 0; - for (Title title : titles) { - width += textRenderer.getWidth(title.getText()) * scale + 10; - } - - if (alignment == UIAndVisualsConfig.Alignment.MIDDLE) { - if (direction == UIAndVisualsConfig.Direction.HORIZONTAL) { - //If middle aligned horizontally, start the xPosition at half of the width to the left. - x = xPos - (width / 2); - } else { - //If middle aligned vertically, start at xPos, we will shift each text to the left later - x = xPos; - } - } - if (alignment == UIAndVisualsConfig.Alignment.LEFT || alignment == UIAndVisualsConfig.Alignment.RIGHT) { - //If left or right aligned, start at xPos, we will shift each text later - x = xPos; - } - - for (Title title : titles) { - - //Calculate which x the text should use - float xToUse; - if (direction == UIAndVisualsConfig.Direction.HORIZONTAL) { - xToUse = alignment == UIAndVisualsConfig.Alignment.RIGHT ? - x - (textRenderer.getWidth(title.getText()) * scale) : //if right aligned we need the text position to be aligned on the right side. - x; - } else { - xToUse = alignment == UIAndVisualsConfig.Alignment.MIDDLE ? - x - (textRenderer.getWidth(title.getText()) * scale) / 2 : //if middle aligned we need the text position to be aligned in the middle. - alignment == UIAndVisualsConfig.Alignment.RIGHT ? - x - (textRenderer.getWidth(title.getText()) * scale) : //if right aligned we need the text position to be aligned on the right side. - x; - } - - //Start displaying the title at the correct position, not at the default position - if (title.isDefaultPos()) { - title.x = xToUse; - title.y = y; - } - - //Lerp the texts x and y variables - title.x = MathHelper.lerp(tickDelta * 0.5F, title.x, xToUse); - title.y = MathHelper.lerp(tickDelta * 0.5F, title.y, y); - - //Translate the matrix to the texts position and scale - context.getMatrices().push(); - context.getMatrices().translate(title.x, title.y, 0); - context.getMatrices().scale(scale, scale, scale); - - //Draw text - context.drawTextWithShadow(textRenderer, title.getText(), 0, 0, 0xFFFFFF); - context.getMatrices().pop(); - - //Calculate the x and y positions for the next title - if (direction == UIAndVisualsConfig.Direction.HORIZONTAL) { - if (alignment == UIAndVisualsConfig.Alignment.MIDDLE || alignment == UIAndVisualsConfig.Alignment.LEFT) { - //Move to the right if middle or left aligned - x += textRenderer.getWidth(title.getText()) * scale + 10; - } - - if (alignment == UIAndVisualsConfig.Alignment.RIGHT) { - //Move to the left if right aligned - x -= textRenderer.getWidth(title.getText()) * scale + 10; - } - } else { - //Y always moves by the same amount if vertical - y += textRenderer.fontHeight * scale + 10; - } - } - } + /** + * The set of titles which will be rendered. + * + * @see #containsTitle(Title) + * @see #addTitle(Title) + * @see #addTitle(Title, int) + * @see #removeTitle(Title) + */ + private static final Set<Title> titles = new LinkedHashSet<>(); + + @Init + public static void init() { + HudRenderEvents.BEFORE_CHAT.register(TitleContainer::render); + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(ClientCommandManager.literal("skyblocker") + .then(ClientCommandManager.literal("hud") + .then(ClientCommandManager.literal("titleContainer") + .executes(Scheduler.queueOpenScreenCommand(TitleContainerConfigScreen::new)))))); + } + + /** + * Returns {@code true} if the title is currently shown. + * + * @param title the title to check + * @return whether the title in currently shown + */ + public static boolean containsTitle(Title title) { + return titles.contains(title); + } + + /** + * Adds a title to be shown + * + * @param title the title to be shown + * @return whether the title is already currently being shown + */ + public static boolean addTitle(Title title) { + if (titles.add(title)) { + title.resetPos(); + return true; + } + return false; + } + + /** + * Adds a title to be shown for a set number of ticks + * + * @param title the title to be shown + * @param ticks the number of ticks to show the title + * @return whether the title is already currently being shown + */ + public static boolean addTitle(Title title, int ticks) { + if (addTitle(title)) { + Scheduler.INSTANCE.schedule(() -> TitleContainer.removeTitle(title), ticks); + return true; + } + return false; + } + + /** + * Stops showing a title + * + * @param title the title to stop showing + */ + public static void removeTitle(Title title) { + titles.remove(title); + } + + private static void render(DrawContext context, RenderTickCounter tickCounter) { + render(context, titles, SkyblockerConfigManager.get().uiAndVisuals.titleContainer.x, SkyblockerConfigManager.get().uiAndVisuals.titleContainer.y, tickCounter.getTickDelta(true)); + } + + protected static void render(DrawContext context, Set<Title> titles, int xPos, int yPos, float tickDelta) { + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + + // Calculate Scale to use + float scale = SkyblockerConfigManager.get().uiAndVisuals.titleContainer.getRenderScale(); + // Grab direction and alignment values + UIAndVisualsConfig.Direction direction = SkyblockerConfigManager.get().uiAndVisuals.titleContainer.direction; + UIAndVisualsConfig.Alignment alignment = SkyblockerConfigManager.get().uiAndVisuals.titleContainer.alignment; + + // x/y refer to the starting position for the text + // If left or right aligned or middle aligned vertically, start at xPos, we will shift each text later + float x = xPos; + // y always starts at yPos + float y = yPos; + + // Calculate the width of combined text + float totalWidth = getWidth(textRenderer, titles); + if (alignment == UIAndVisualsConfig.Alignment.MIDDLE && direction == UIAndVisualsConfig.Direction.HORIZONTAL) { + // If middle aligned horizontally, start the xPosition at half of the width to the left. + x = xPos - totalWidth / 2; + } + + for (Title title : titles) { + //Calculate which x the text should use + float xTextLeft = x; + if (alignment == UIAndVisualsConfig.Alignment.RIGHT) { + //if right aligned we need the text position to be aligned on the right side. + xTextLeft = x - textRenderer.getWidth(title.getText()) * scale; + } else if (direction == UIAndVisualsConfig.Direction.VERTICAL && alignment == UIAndVisualsConfig.Alignment.MIDDLE) { + //if middle aligned we need the text position to be aligned in the middle. + xTextLeft = x - (textRenderer.getWidth(title.getText()) * scale) / 2; + } + + //Start displaying the title at the correct position, not at the default position + if (title.isDefaultPos()) { + title.x = xTextLeft; + title.y = y; + } + + //Lerp the texts x and y variables + title.x = MathHelper.lerp(tickDelta * 0.5F, title.x, xTextLeft); + title.y = MathHelper.lerp(tickDelta * 0.5F, title.y, y); + + //Translate the matrix to the texts position |
