Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,28 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig
.build())
.build())

//Time Input Calculator
.group(OptionGroup.createBuilder()
.name(Component.translatable("skyblocker.config.uiAndVisuals.timeInputCalculator"))
.collapsed(true)
.option(Option.<Boolean>createBuilder()
.name(Component.translatable("skyblocker.config.uiAndVisuals.timeInputCalculator.enabled"))
.description(Component.translatable("skyblocker.config.uiAndVisuals.timeInputCalculator.enabled.@Tooltip"))
.binding(defaults.uiAndVisuals.timeInputCalculator.enabled,
() -> config.uiAndVisuals.timeInputCalculator.enabled,
newValue -> config.uiAndVisuals.timeInputCalculator.enabled = newValue)
.controller(ConfigUtils.createBooleanController())
.build())
.option(Option.<Boolean>createBuilder()
.name(Component.translatable("skyblocker.config.uiAndVisuals.timeInputCalculator.closeSignsWithEnter"))
.description(Component.translatable("skyblocker.config.uiAndVisuals.timeInputCalculator.closeSignsWithEnter.@Tooltip"))
.binding(defaults.uiAndVisuals.timeInputCalculator.closeSignsWithEnter,
() -> config.uiAndVisuals.timeInputCalculator.closeSignsWithEnter,
newValue -> config.uiAndVisuals.timeInputCalculator.closeSignsWithEnter = newValue)
.controller(ConfigUtils.createBooleanController())
.build())
.build())

//Flame Overlay
.group(OptionGroup.createBuilder()
.name(Component.translatable("skyblocker.config.uiAndVisuals.flameOverlay"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ public class UIAndVisualsConfig {

public InputCalculator inputCalculator = new InputCalculator();

public TimeInputCalculator timeInputCalculator = new TimeInputCalculator();

public FlameOverlay flameOverlay = new FlameOverlay();

public CompactDamage compactDamage = new CompactDamage();
Expand Down Expand Up @@ -411,6 +413,12 @@ public static class InputCalculator {
public boolean closeSignsWithEnter = true;
}

public static class TimeInputCalculator {
public boolean enabled = true;

public boolean closeSignsWithEnter = true;
}

public static class FlameOverlay {
public int flameHeight = 100;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.skyblock.bazaar.BazaarQuickQuantities;
import de.hysky.skyblocker.skyblock.calculators.SignCalculator;
import de.hysky.skyblocker.skyblock.calculators.SignTimeCalculator;
import de.hysky.skyblocker.skyblock.speedpreset.SpeedPresets;
import de.hysky.skyblocker.utils.Utils;
import net.minecraft.ChatFormatting;
Expand All @@ -14,6 +15,7 @@
import net.minecraft.client.gui.screens.inventory.AbstractSignEditScreen;
import net.minecraft.client.input.KeyEvent;
import net.minecraft.network.chat.Component;
import org.jspecify.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
Expand Down Expand Up @@ -59,18 +61,28 @@ protected AbstractSignEditScreenMixin(Component title) {
context.guiWidth() / 2, 55, 0xFFFFFFFF);
}
}
//if the sign is being used to enter number send it to the sign calculator
else if (isInputSign() && config.uiAndVisuals.inputCalculator.enabled) {
SignCalculator.renderCalculator(context, messages[0], context.guiWidth() / 2, 55);
else {
SignTimeCalculator.TimeType timeInputType = getTimeInputType();
if (timeInputType != null) {
if (config.uiAndVisuals.timeInputCalculator.enabled) {
SignTimeCalculator.renderTime(context, messages[0], timeInputType, context.guiWidth() / 2, 55);
}
}
//if the sign is being used to enter number send it to the sign calculator
else if (isInputSign() && config.uiAndVisuals.inputCalculator.enabled) {
SignCalculator.renderCalculator(context, messages[0], context.guiWidth() / 2, 55);
}
}
}
}

@Inject(method = "keyPressed", at = @At("HEAD"))
private void skyblocker$keyPressed(KeyEvent input, CallbackInfoReturnable<Boolean> cir) {
if (SkyblockerConfigManager.get().uiAndVisuals.inputCalculator.closeSignsWithEnter
&& Utils.isOnSkyblock() && isInputSign()
&& (input.isConfirmation())) this.onClose();
if (input.isConfirmation() && Utils.isOnSkyblock()
&& (
SkyblockerConfigManager.get().uiAndVisuals.timeInputCalculator.closeSignsWithEnter && getTimeInputType() != null
|| SkyblockerConfigManager.get().uiAndVisuals.inputCalculator.closeSignsWithEnter && isInputSign()
)) this.onClose();
}

@Inject(method = "onDone", at = @At("HEAD"))
Expand All @@ -84,6 +96,12 @@ else if (isInputSign() && config.uiAndVisuals.inputCalculator.enabled) {
messages[0] = String.valueOf(presets.getPreset(messages[0]));
}
}
else if (getTimeInputType() != null) {
if (config.uiAndVisuals.timeInputCalculator.enabled) {
String value = SignTimeCalculator.getNewValue();
if (value != null) messages[0] = value;
}
}
//if the sign is being used to enter number get number from calculator for if maths has been done
else if (isInputSign() && config.uiAndVisuals.inputCalculator.enabled) {
boolean isPrice = messages[2].contains("price");
Expand All @@ -99,6 +117,10 @@ else if (isInputSign() && config.uiAndVisuals.inputCalculator.enabled) {
@Unique
private static final String SPEED_INPUT_MARKER = "speed cap!";
@Unique
private static final String TIME_INPUT_MARKER_HOURS = "hours";
@Unique
private static final String TIME_INPUT_MARKER_MINUTES = "minutes";
@Unique
private static final String INPUT_SIGN_MARKER = "^^^^^^^^^^^^^^^";
/** This is used for some things like the super craft amount input */
@Unique
Expand All @@ -111,6 +133,20 @@ private boolean isSpeedInputSign() {
return messages[3].equals(SPEED_INPUT_MARKER);
}

@Unique
private SignTimeCalculator.@Nullable TimeType getTimeInputType() {
if (messages[1].equals(INPUT_SIGN_MARKER)) {
if (messages[3].endsWith(TIME_INPUT_MARKER_HOURS)) {
return SignTimeCalculator.TimeType.HOURS;
}
if (messages[3].endsWith(TIME_INPUT_MARKER_MINUTES)) {
return SignTimeCalculator.TimeType.MINUTES;
}
}

return null;
}

/**
* Used to exclude search signs with {@link AbstractSignEditScreenMixin#INPUT_SIGN_MARKER}.
* <br> Works for /recipes & /shards signs
Expand All @@ -131,6 +167,10 @@ private boolean isAltInputSearchSign() {

@Unique
private boolean isInputSign() {
return messages[1].equals(INPUT_SIGN_MARKER) && !isInputSearchSign() || messages[1].equals(ALT_INPUT_SIGN_MARKER) && !isAltInputSearchSign() || messages[1].equals(BAZAAR_FLIP_MARKER);
return (
messages[1].equals(INPUT_SIGN_MARKER) && !isInputSearchSign()
|| messages[1].equals(ALT_INPUT_SIGN_MARKER) && !isAltInputSearchSign()
|| messages[1].equals(BAZAAR_FLIP_MARKER)
) && getTimeInputType() == null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package de.hysky.skyblocker.skyblock.calculators;

import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import org.jetbrains.annotations.VisibleForTesting;

import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SignTimeCalculator
{
public enum TimeType {
HOURS, MINUTES
}

private static final Minecraft CLIENT = Minecraft.getInstance();
private static final Pattern TIME_CODE_PATTERN = Pattern.compile("(\\d+\\.\\d+|\\d+)(\\D+)?");
private static final int SECONDS_PER_DAY = 86400;
private static final short SECONDS_PER_HOUR = 3600;
private static final byte SECONDS_PER_MINUTE = 60;

private static String lastInput;
private static long seconds;
private static Component error = null;

public static void renderTime(GuiGraphics context, String message, TimeType type, int renderX, int renderY) {
calculate(message, type);
render(context, renderX, renderY);
}

@VisibleForTesting
public static void calculate(String message, TimeType type) {
//only update if new input
if (message.equals(lastInput)) return;
lastInput = message;

if (message.isBlank()) {
seconds = -1;
error = Component.translatable("skyblocker.config.uiAndVisuals.timeInputCalculator.emptyInputError").withStyle(ChatFormatting.RED);
return;
}

long newSeconds = 0;
for (String segment : message.trim().split(" +")) {
Matcher matcher = TIME_CODE_PATTERN.matcher(segment);
if (matcher.matches()) {
String numberString = matcher.group(1);
if (numberString.startsWith("-")) {
seconds = -1;
error = Component.translatable("skyblocker.config.uiAndVisuals.timeInputCalculator.invalidNumberError", numberString).withStyle(ChatFormatting.RED);
return;
}
double number;
try {
number = Double.parseDouble(numberString);
} catch (NumberFormatException e) {
seconds = -1;
error = Component.translatable("skyblocker.config.uiAndVisuals.timeInputCalculator.invalidNumberError", numberString).withStyle(ChatFormatting.RED);
return;
}

String timeUnitString = matcher.group(2);
if (timeUnitString == null || timeUnitString.isEmpty()) {
newSeconds += switch (type) {
case HOURS -> Math.round(number * SECONDS_PER_HOUR);
case MINUTES -> Math.round(number * SECONDS_PER_MINUTE);
};
}
//mimics how Hypixel parses numbers, except also allowing plurals
else if ("days".startsWith(timeUnitString.toLowerCase(Locale.ENGLISH))) {
newSeconds += Math.round(number * SECONDS_PER_DAY);
} else if ("hours".startsWith(timeUnitString.toLowerCase(Locale.ENGLISH))) {
newSeconds += Math.round(number * SECONDS_PER_HOUR);
} else if ("minutes".startsWith(timeUnitString.toLowerCase(Locale.ENGLISH))) {
newSeconds += Math.round(number * SECONDS_PER_MINUTE);
} else if ("seconds".startsWith(timeUnitString.toLowerCase(Locale.ENGLISH))) {
//note/fun fact: for some reason Hypixel only allows up to "secon", not "second"
newSeconds += Math.round(number);
} else {
seconds = -1;
error = Component.translatable("skyblocker.config.uiAndVisuals.timeInputCalculator.invalidTimeUnit", timeUnitString).withStyle(ChatFormatting.RED);
return;
}
} else {
seconds = -1;
error = Component.translatable("skyblocker.config.uiAndVisuals.timeInputCalculator.invalidInputSpecific", segment).withStyle(ChatFormatting.RED);
return;
}
}

seconds = newSeconds;
error = null;
}

public static String getNewValue() {
if (seconds == -1) {
//if calculator is not activated or just invalid input return what the user typed in
return lastInput;
}

//we can just return the total seconds, Hypixel converts it for us :)
return seconds + "s";
}

private static void render(GuiGraphics context, int renderX, int renderY) {
Component text;
if (seconds == -1) {
text = error != null ? error : Component.translatable("skyblocker.config.uiAndVisuals.timeInputCalculator.invalidInput").withStyle(ChatFormatting.RED);
} else {
long remainingSeconds = seconds;
MutableComponent timeText = Component.empty();
remainingSeconds = appendTimeComponent(timeText, remainingSeconds, SECONDS_PER_DAY, "day");
remainingSeconds = appendTimeComponent(timeText, remainingSeconds, SECONDS_PER_HOUR, "hour");
remainingSeconds = appendTimeComponent(timeText, remainingSeconds, SECONDS_PER_MINUTE, "minute");
appendTimeComponent(timeText, remainingSeconds, 1, "second");
text = timeText.withStyle(ChatFormatting.GREEN);
}

context.drawCenteredString(CLIENT.font, text, renderX, renderY, 0xFFFFFFFF);
}

private static long appendTimeComponent(MutableComponent component, long seconds, int secondsPerUnit, String translationKeyUnit)
{
long units = seconds / secondsPerUnit; //long division -> cuts off decimal places automatically
if (units > 0) {
seconds -= units * secondsPerUnit;
if (!component.equals(CommonComponents.EMPTY)) {
component.append(" ");
}
component.append(Component.translatable(
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit." + translationKeyUnit + (units == 1 ? "" : "s"),
units
));
}
return seconds;
}
}
18 changes: 18 additions & 0 deletions src/main/resources/assets/skyblocker/lang/de_de.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,24 @@
"skyblocker.config.uiAndVisuals.tabHud.tabHudScale.@Tooltip": "Wert in %, relativ zur Skalierung des Vanilla-GUIs",
"skyblocker.config.uiAndVisuals.bars.enableBars": "Balken aktivieren",
"skyblocker.config.uiAndVisuals.hideEmptyTooltips": "Leere Item-Tooltips in Menüs verstecken",
"skyblocker.config.uiAndVisuals.timeInputCalculator": "Zeiteingaberechner",
"skyblocker.config.uiAndVisuals.timeInputCalculator.closeSignsWithEnter": "Schilder mit Eingabetaste schließen",
"skyblocker.config.uiAndVisuals.timeInputCalculator.closeSignsWithEnter.@Tooltip": "Schließe das aktuell geöffnete Schildfenster mit der Eingabetaste",
"skyblocker.config.uiAndVisuals.timeInputCalculator.emptyInputError": "Eingabe ist leer",
"skyblocker.config.uiAndVisuals.timeInputCalculator.enabled": "Zeiteingaberechner aktivieren",
"skyblocker.config.uiAndVisuals.timeInputCalculator.enabled.@Tooltip": "Zeigt Zeiteinheiten an und konvertiert diese beim Eingeben von Zeitwerten wie Dauer für das Auktionshaus.\n(Beispiel: '0.5d 2h' = 14 Stunden)\n Einheiten:\n s(econds)\n m(inutes)\n h(ours)\n d(ays)",
"skyblocker.config.uiAndVisuals.timeInputCalculator.invalidInput": "Ungültige Eingabe",
"skyblocker.config.uiAndVisuals.timeInputCalculator.invalidInputSpecific": "Ungültige Eingabe '%s'",
"skyblocker.config.uiAndVisuals.timeInputCalculator.invalidNumberError": "Ungültige Zahl '%s'",
"skyblocker.config.uiAndVisuals.timeInputCalculator.invalidTimeUnit": "Ungültige Zeiteinheit '%s'",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.day": "%s Tag",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.days": "%s Tage",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.hour": "%s Stunde",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.hours": "%s Stunden",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.minute": "%s Minute",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.minutes": "%s Minuten",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.second": "%s Sekunde",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.seconds": "%s Sekunden",
"skyblocker.config.otherLocations": "Andere Orte",
"skyblocker.config.dungeons": "Dungeons",
"skyblocker.config.dungeons.map.enableMap": "Karte aktivieren",
Expand Down
19 changes: 19 additions & 0 deletions src/main/resources/assets/skyblocker/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -1390,6 +1390,25 @@
"skyblocker.config.uiAndVisuals.teleportOverlay.showWhenInAir": "Show Overlay Mid Air",
"skyblocker.config.uiAndVisuals.teleportOverlay.teleportOverlayColor": "Teleport Overlay Color",

"skyblocker.config.uiAndVisuals.timeInputCalculator": "Time Input Calculator",
"skyblocker.config.uiAndVisuals.timeInputCalculator.closeSignsWithEnter": "Close signs with enter",
"skyblocker.config.uiAndVisuals.timeInputCalculator.closeSignsWithEnter.@Tooltip": "Close the current open sign screen with the enter key",
"skyblocker.config.uiAndVisuals.timeInputCalculator.emptyInputError": "Input is empty",
"skyblocker.config.uiAndVisuals.timeInputCalculator.enabled": "Enable Time Input Calculator",
"skyblocker.config.uiAndVisuals.timeInputCalculator.enabled.@Tooltip": "Displays and converts time units when inputting time values such as duration for the ah.\nExample: '0.5d 2h' = 14 Hours\n Units:\n s(econds)\n m(inutes)\n h(ours)\n d(ays)",
"skyblocker.config.uiAndVisuals.timeInputCalculator.invalidInput": "Invalid input",
"skyblocker.config.uiAndVisuals.timeInputCalculator.invalidInputSpecific": "Invalid input '%s'",
"skyblocker.config.uiAndVisuals.timeInputCalculator.invalidNumberError": "Invalid number '%s'",
"skyblocker.config.uiAndVisuals.timeInputCalculator.invalidTimeUnit": "Invalid time unit '%s'",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.day": "%s Day",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.days": "%s Days",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.hour": "%s Hour",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.hours": "%s Hours",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.minute": "%s Minute",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.minutes": "%s Minutes",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.second": "%s Second",
"skyblocker.config.uiAndVisuals.timeInputCalculator.unit.seconds": "%s Seconds",

"skyblocker.config.uiAndVisuals.titleContainer": "Title Container",
"skyblocker.config.uiAndVisuals.titleContainer.@Tooltip": "Used to display multiple titles at once, Example use: Vampire Slayer",
"skyblocker.config.uiAndVisuals.titleContainer.alignment.LEFT": "Left",
Expand Down